why self-type class can declare class - scala

I know Scala can only mixin traits, it makes sense for dependency injection and cake pattern. My question is why I can still declare a class which need another "class" but not trait.
Code:
class C
class D { self : C =>}
This is still complied successfully. I thought it should failed compiled, because at this point how can new instance D (C is class not trait).
Edit:
when try to instantiate D:
new D with C //compilation fail class C needs to be a trait to be mixed in.

You should explicitly make class D to extends C as follows:
class C
class D extends C { self: C => }
Furthermore, you can refer to the post Does a class with a self type of another class make sense?, which explains this problem clearly.

Related

Scala Nested Object Serialization

Hi I have a case class A which contains variables pointing to another class B (with companion object, which has variables pointing to yet another class C which also has companion object). class B and C are from other libraries. What is the easier way that I could serialize my case class A?
case class A() {
val b = B
}
//B & C are defined in a library that I have no control of
object B {
val c = C
}
class B{
...
}
object C{
...
}
class C{
...
}
If these classes are already Serializable, you don't need to do anything special, so the rest of the answer assumes they aren't.
If these fields can be reconstructed from others, mark them as #transient and implement readObject (as described in http://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html) to restore them. Unfortunately, you can't initialize vals in readObject and will have to write something like
case class A() {
private var _b = B
def b = _b
}
If they can't, you need to store something they can be restored from in writeObject as well.
Finally, you can use one of the third-party serialization libraries like Kryo or Scala Pickling, because basically all of them allow to add support for types not under your control (otherwise they couldn't work with the types in standard Java library!)

Scala - choose a method of one trait over another

I am new to scala. I was learning traits and it seems that they can have concrete methods. Here is the code I have written.
trait A{
def print : Unit = {
println("I am in A")
}
}
trait B{
def print : Unit = {
println("I am in B")
}
}
trait C {
def print : Unit = {
println("I am in C")
}
}
class D extends A with B with C{
}
object Main extends App {
val d: D = new D
d.print
}
It is giving a compilation error obviously. The compiler is asking me to override the print method in D. I don't want to write a new method. I just want to choose C's print method over others. Is there any way I can choose only C's print method? I hope I have made myself clear. I am sorry if the question sounds stupid. I am trying to learn. Thanks in advance.
#S.K, so the last trait I mix in is the super class?
If you look at the documention of Scala trait, whenever scala compiler see any class with multiple parent scala compiler will place all the classes in stackable form.
so If A extends B with C will become --> A->B->C and when you invoke super from you base class A it will consider method like C->B (C then B).
same way if you make A extends C with B will become --> A->C->B and when you invoke it compiler will consider B->C (B then C).
Please see more detials on scala trait stackable at below link.
Scala's Stackable Trait Pattern
I am agree with S.K what is a problem to override in class D.
One way you are extending your D class with C and without overriding how can you get the handle of method in C?
You have to override in order to call it's method.

Injecting a new class into the coffeescript inheritance chain

I have three coffeescript classes, set up like this:
class A
class C extends A
class B
so that the prototype chain looks like this:
A -> C
B
and I need the prototype chain to look like this:
A -> B -> C
The catch being that I can't touch the definitions of A and C.
What I'd like to do is make an inject function that can be called like this:
inject B, C
that injects B into C's prototype chain before A, and then set up B's prototype chain to whatever C's was before the injection.
I thought this would be simple, something like
C extends (B extends C.prototype)
But unfortunately, things aren't quite that simple, due to all the prototype/__super__ magic that coffeescript does. Does anyone know how to inject into the prototype chain such that it's basically like you said class C extends B and class B extends A in the first place?
Many thanks.
Clarification: The below code DOES NOT WORK, because the properties fail to be copied over.
class A
foo: 1
class B
bar: 2
class C extends A
baz: 3
B extends A
C extends B
c = new C
console.log c.foo
console.log c.bar
console.log c.baz
[Update: I originally answered that C extends B; B extends A would work. This does indeed make C instanceof B and B instanceof A become true, but it doesn't copy prototypal properties as desired. So, I've rewritten the answer.]
Let's walk through this:
class A
foo: 1
class B
bar: 2
class C extends A
baz: 3
At this point, C::foo is 1 and C::baz is 3. If we then run
C extends B
that overwrites C's existing prototype with an instance of B (child.prototype = ...), so only C::bar is defined.
This doesn't happen when we use the class X extends Y syntax because properties are attached to X's prototype only after its prototype is overwritten. So, let's write a wrapper around extends that saves existing prototype properties, then restores them:
inherits = (child, parent) ->
proto = child::
child extends parent
child::[x] = proto[x] for own x of proto when x not of child::
child
Applying this to our example:
inherits B, A
inherits C, B
console.log new C instanceof B, new B instanceof A # true, true
console.log B::foo, B::bar, B::baz # 1, 2, undefined
console.log C::foo, C::bar, C::baz # 1, 2, 3
If you'd like to learn more about the inner workings of CoffeeScript classes, you might want to check out my book on CoffeeScript, published by the fine folks at PragProg. :)

Seamless weaving of trait

I would like to automatically weave the definition of a new function say introduced by an extending trait Ext into an abstract class A:
class Base {
abstract class A
class B extends A
case class C extends A
}
trait Ext extends Base {
trait A extends super.A {
def say = "hello"
}
}
object Test extends Base with Ext {
val b = new B
b.say
}
However, I obtain the following error:
<console>:12: error: value say is not a member of Test.B
b.say
Any way of doing it?
It seems you are trying to use virtual classes, which is a feature not available in Scala.
Once A and B are defined they can't be redefined (like method overriding).
abstract class A
class B extends A
On the other hand, given your example, your objective could be achieved by a simple mixin. Here it is with few rewrites:
class Base {
abstract class A
class B extends A
case class C extends A
}
trait Ext extends Base {
trait CanSay extends A {
def say = "hello"
}
}
object Test extends Base with Ext {
val b = new B with CanSay
def apply = b.say
}
Test.apply
No sure it will really help, but at least will help you understand what is going on.
Okay, as I said in a comment, it's not entirely clear what you're trying to do here, so I can't really try to suggest ways to do it. However, the approach you're using at the moment will not work.
Consider the class Hierarchy in this situation. At the base, we have A, which is then subclassed with B (in Base) and with Ext.A. These are not related save by their shared supertype, so you'll never find a say method on an instance of B.
The confusion possibly arises through the use of the word abstract. An abstract modifier on a class (even an inner class) does not make it an abstract member of the parent class, but denotes that it itself may have abstract members. There are ways of giving a class an abstract class member - through type parameters or type members. Unfortunately, you cannot derive from these AFAIK.

Mixing multiple traits in Scala

Quick note: Examples from the tutorial Scala for Java Refugees Part 5: Traits and Types.
Suppose I have the traits Student, Worker, Underpaid, and Young.
How could I declare a class (not instance), CollegeStudent, with all these traits?
Note: I am aware of the simplests cases, such as CollegeStudent with one or two Traits:
class CollegeStudent extends Student with Worker
It is easy, when declaring a class you just use the "with" keyword as often as you want
class CollegeStudent extends Student with Worker with Underpaid with Young
the order of the traits can be important if a trait is changing the behavior of the class, it all depends on traits you are using.
Also if you don't want to have a class which always uses the same traits you can use them later:
class CollegeStudent extends Student
new CollegeStudent with Worker with Underpaid with NotSoYoungAnymore
I think that it is very important to explain not only the syntax, but also which role does the ordering of the traits play. I found the explanation in Jason Swartz's Learning Scala (page 177) quite enlightning.
A Scala class can extend multiple traits at once, but JVM classes can extend only one parent class. The Scala compiler solves this by creating "copies of each trait to form a tall, single-column hierarchy of the
class and traits", a process known as linearization.
In this context, extending multiple traits with identical field names would fail to compile, exactly the same "as if you were extending a class and providing your own version of a method but failed to add an override keyword".
And since it determines the shape of the inheritance tree, the linearization order is indeed one very important question to regard. As an example, class D extends A with B with C (where A is a class and B
and C are traits) would become class D extends C extends B extends A. The following few lines, also from the book, illustrate that perfectly:
trait Base { override def toString = "Base" }
class A extends Base { override def toString = "A->" + super.toString }
trait B extends Base { override def toString = "B->" + super.toString }
trait C extends Base { override def toString = "C->" + super.toString }
class D extends A with B with C { override def toString = "D->" + super.toString }
A call to new D() would have the REPL print the following:
D->C->B->A->Base
Which perfectly reflects the structure of the linearized inheritance graph.