What is meant by this is the following weirdness:
trait A {
val i: String
def j: String
}
class C extends A {
println ("val i = " + i)
println ("def j = " + j)
val i = "i"
def j = "j"
}
val c = new C
// prints
// val i = null
// def j = j
So, as you can see i
is initialised to it default value (null
for AnyRef
) before it is finally overridden by the constructor in C
. (def
declarations are re-referenced immediately.)
To avoid this one would have to put the val
initialisations to the beginning of the constructor, if possible.
Additional weirdness (and how to solve it) in the following case
Consider
trait A {
val i: String
def j: String
}
abstract class D extends A {
println ("val i = " + i)
println ("def j = " + j)
}
class C extends D {
val i = "i"
def j = "j"
}
val c = new C
// prints
// val i = null
// def j = null
Now we seem to be out of luck; it looks as if there is no chance for us to initialise val i
and def j
before our superclass D
tries to print them.
In order to solve this problem, we must use Early definitions (§5.1.6 Scala reference):
class C extends {
val i = "i"
def j = "j"
} with D
val c = new C
// prints
// val i = i
// def j = j
And it works!