The following Scala 3 code
trait MyTrait:
println("MyTrait initialization – start")
val value: Int
def data: String
println(s"MyTrait initialized end with value=$value, data=$data")
@main
def main(): Unit = {
new MyTrait: // anonymous subclass
println("Anonymous subclass initialization – start")
val value = 1
def data =
println("Calling data inside anonymous subclass")
"abc"
println("Anonymous subclass initialization – end")
}
prints
MyTrait initialization – start
Calling data inside anonymous subclass
MyTrait initialized end with value=0, data=abc
Anonymous subclass initialization – start
Anonymous subclass initialization – end
I don't understand why it prints data=abc
. Shouldn't it print some default value or compilation error eccur?
The initialization order is MyTrait
followed by the anonymous subclass. In MyTrait
, abstract members should have been set to their default value – this holds for value
, as it prints 0
. However, for a method data
, it somehow skips this initialization order and calls the concrete data
method from the anonymous subclass before its initialization should happen.
CodePudding user response:
val
s and var
s (or technically the fields backing them) are initialized with default values. def
s (aka methods) are effectively bound at compile time and virtual method dispatch means that the methods may be called before the constructor for the class has completed.
The effective flow is:
- allocate memory for the anonymous subclass (at this point
def data
is bound to the anonymous subclass's implementation and fields have their default values) - call the anonymous subclass's constructor
- ...which calls the trait's constructor
- then runs the rest of the body of the subclass's constructor