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
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.
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 val
s to avoid issues like this.