For the question of the difference between new { type T = Int ; val init = 10 } new { type T = Int ; val init = 10 } with AbsCell2 and new AbsCell2 { type T = Int ; val init = 10 } new AbsCell2 { type T = Int ; val init = 10 } .
The first is the so-called early initializers or pre-initialized fields (mentioned in the chapter “Abstract members” in “Scala Programming”). It allows the subclass to initialize the fields before calling the superclass. In this case, init was already set as 10 before AbsCell2 was initialized.
The latter is ordinary inheritance, it creates an anonymous class, and then extends AbsCell2, as:
class AbsCell' extends AbsCell { type T = Int val init = 10 }
However, the anonymous class is initialized after the abstract class AbsCell2, so init is not available in the initialization of itself, namely: init is the default value for Type, 0 in this case. Therefore you get 0 in print. A.
use scalac -Xprint:all Test.scala , you will see the following:
abstract class AbsCell2 extends Object { <stable> <accessor> def init(): Object; .... def <init>(): AbsCell2 = { AbsCell2.super.<init>(); AbsCell2.this.value = { scala.this.Predef.println("Hello ".+(AbsCell2.this.init())); AbsCell2.this.init() }; () } }; // normal initialization final class anon$1 extends AbsCell2 { private[this] val init: Int = _; <stable> <accessor> def init(): Int = anon$1.this.init; .... def <init>(): <$anon: AbsCell2> = { anon$1.super.<init>(); anon$1.this.init = 10; () } }; // early initialization final class anon$2 extends AbsCell2 { private[this] val init: Int = _; <stable> <accessor> def init(): Int = anon$2.this.init; .... def <init>(): <$anon: AbsCell2> = { val init: Int = 10; anon$2.this.init = init; anon$2.super.<init>(); () } }
From the code we can see that for normal initialization, init has a value of 3 after the superclass of AbsCell2 is initialized, when AbsCell2.this.init () is called, it actually refers to the initialization field of the subclass and 3 is not set yet, so we get the default value of the type. In contrast, early initialization first sets up init 3 and then causes the class to be superclassed.
source share