Search code examples
scalamixins

Scala mixin sets overridden variable to null


I have the following situation:

class A {
  val text = "Test"
  //some initialization things using text. here represented by println
  println(text)
}

now I want to write unit tests for the class and therefore change the value of text for this purpose.

trait Test extends A {
  override val text = "Hello"
}

class B extends A with Test 

The problem is that now if I create an instance of B the value of text is set to "Hello" as expected but all the initialization steps in A get a value of null for text

See this fiddle for demo

My question is why is the variable null to the statements in the original class A? I guess having the old value seems more logical than just having no value all of a sudden.


Solution

  • When you write val text = ..., the compiler generates a private final field (let's call it _text) and a method for accessing it. This happens in both A and B. Constructor of B calls A's constructor first, but the text method it uses is B's; so it accesses B._text, which isn't initialized yet!

    As an alternative to def in @DennisTraub's answer, you can also use a lazy val to avoid recalculating the answer (def is better in this case, though). In my opinion, you generally shouldn't override vals to avoid issues like this.