Possible Duplicate:
Scala: forward references - why does this code compile?
object Omg {
class A
class B(val a: A)
private val b = new B(a)
private val a = new A
def main(args: Array[String]) {
println(b.a)
}
}
the following code prints "null". In java. similar construction doesn't compile because of invalid forward reference. The question is - why does it compile well in Scala? Is that by design, described in SLS or simply bug in 2.9.1?
As @paradigmatic states, it's not really a bug. It's the initialization order, which follows the declaration order. It this case,
a
is null whenb
is declared/init-ed.Changing the line
private val b = new B(a)
toprivate lazy val b = new B(a)
will fix issue, since using lazy will delay the init. of b to it's first usage.It's very likely that this behavior is described in the SLS.
If this is a concern, compile with
-Xcheckinit
during development and iterate until the exceptions go away.Spec 5.1 for template body statements executed in order; beginning of 4.0 for forward references in blocks.
Forward References - why does this code compile?
It's not a bug, but a classic error when learning Scala. When the object
Omg
is initialized, all values are first set to the default value (null
in this case) and then the constructor (i.e. the object body) runs.To make it work, just add the
lazy
keyword in front of the declaration you are forward referencing (valuea
in this case):Value
a
will then be initialized on demand.This construction is fast (the values are only initialized once for all application runtime) and thread-safe.
The way that I understand it, this has to do with how the Scala classes are created. In Java, the class defined above would be initializing the variables inline, and since
a
had not been defined yet, it could not be compiled. However, in Scala it is more the equivalent of this in Java (which should also produce null in the same scenario):Alternately, you could make your declaration of
b
lazy, which would defer setting the value until it is called (at which time a will have been set).