有關與AbsCell2和new AbsCell2 { type T = Int ; val init = 10 }
new { type T = Int ; val init = 10 }
之間的差異問題。
第一個是所謂的早期初始化或預先初始化的字段(在Programming Scala中的抽象成員一章中提到過)。它允許子類在超類被調用之前初始化字段 在這種情況下,init有。已經AbsCell2的初始化之前被設定爲10
後者是正常的繼承,它會創建一個匿名類,然後擴展AbsCell2,就像:
class AbsCell' extends AbsCell {
type T = Int
val init = 10
}
然而,匿名類被後初始化抽象類AbsCell2,所以init在其本身的初始化中不可用,即init是Type的默認值,在這種情況下爲0。因此,您在打印得0
使用scalac -Xprint:all Test.scala
,你會看到以下內容:。
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>();
()
}
}
從代碼中,我們可以看到,對於正常的初始化,初始化時的初始化後設置爲3超類AbsCell2,當AbsCell2.this.init()被調用時,它實際上是指子類的init字段,而3還沒有設置,所以我們得到默認的類型值。相反,早期初始化首先將init設置爲3然後調用超級類初始化。
本示例借用Martin Ordersky提供的演示文稿。 http://lampwww.epfl.ch/~odersky/ –
但是現在在REPL中執行'cell.init',它會_will_向您顯示10.您的問題是爲什麼在對象初始化之前它不打印10? –
我想愛國者也在問爲什麼'細胞。get'返回0,以及如何讓它返回10. –