Since vals are not initialized more than once, x is actually null (or false for the default Boolean ) during initialization of Foo , and then initialized in an anonymous class that extends Foo in your example.
We can test it easier with AnyRef :
class Foo { val x = "" val f = if (x == null) "x is null" else "not null" } scala> new Foo { override val x = "a" }.f res10: String = x is null scala> new Foo {}.f res11: String = not null
There is a full explanation in the Scala FAQ . Excerpts:
Naturally, when val is redefined, it is not initialized more than once. Thus, although x2 in the above example seems to be defined at every point, it is not: an overridden val will appear to be zero when constructing superclasses, just like the abstract value val.
An easy way to avoid this would be to use a lazy val or def if the reference to Val can be overridden.
Alternatively, you can use the -Xcheckinit flag for the compiler to warn you of potential initialization errors like this.
source share