Reputation: 6039
Consider the following program:
abstract class Learnable {
val classifier = 1
val classifierWithVal = classifier
def classifierWithDef = classifier
lazy val classifierWithLazyVal = classifier
var classifierWithVar = classifier
}
object someClassifier extends Learnable {
override val classifier = 2
}
object HelloWorld {
def main(args: Array[String]): Unit = {
println(someClassifier.classifier) // expect and print 2
println(someClassifier.classifierWithDef) // expected and printed 2
println(someClassifier.classifierWithLazyVal) // expected and printed 2
println(someClassifier.classifierWithVal) // expected 1, but printed 0
println(someClassifier.classifierWithVar) // expected 1, but printed 0
}
}
it contains an abstract
class and an object which instantiates and extends the class. The question is why the last two lines in the HelloWorld
program print 0; I was expecting them to print 1 since they are initialized to 1 in the definition of abstract class Learnable
. (otherwise what was the point of initialization??)
Upvotes: 0
Views: 111
Reputation: 7348
This is due to Scala's initialization order http://docs.scala-lang.org/tutorials/FAQ/initialization-order.html
In the link there's explanation and few solutions (Use lazy vals, Use early definitions, Use constant value definitions
Short part of the explanation-
Naturally when a val is overridden, it is not initialized more than once. So though x2 in the above example is seemingly defined at every point, this is not the case: an overridden val will appear to be null during the construction of superclasses, as will an abstract val.
Sample from Scala's documentaion-
abstract class A {
val x1: String
val x2: String = "mom"
println("A: " + x1 + ", " + x2)
}
class B extends A {
val x1: String = "hello"
println("B: " + x1 + ", " + x2)
}
class C extends B {
override val x2: String = "dad"
println("C: " + x1 + ", " + x2)
}
scala> new C
A: null, null
B: hello, null
C: hello, dad
Upvotes: 1