Daniel
Daniel

Reputation: 6039

Scala: Working with values from the abstract class

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

Answers (1)

Maxim
Maxim

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

Related Questions