2011-04-22 93 views
2

考慮下面的代碼:斯卡拉2.8:如何初始化子類

abstract class X { 
    def a:Unit 
    a 
} 

class Y extends X { 
    var s:String = "Hello" 
    def a:Unit = println ("String is "+s) 
} 

這給出了以下的輸出:

scala> new Y 
String is null 
res6: Y = [email protected] 

我怎樣才能得到父類X等待s是調用時初始化a

回答

6

父項的字段和父構造函數總是初始化並在chil之前運行dren的領域和構造函數。這意味着a的呼叫發生在您的子類中設置了var s之前。

通常,從構造函數調用虛方法是一個壞主意; C++甚至不允許它(或者,而不是禁止它,當從超類的構造函數調用時,不會調用在子類中實現的方法)。

但是,如果您將var s轉換爲或def,您可以修改它。 lazy val在第一次訪問它們的值時被初始化,不管由誰來進行; def s不存在初始化問題,如var s或val s。但是,請注意不要在a的實現中調用任何其他未初始化的結構,因爲同樣的問題會再次出現。

編輯:

您還可以使用Scala的「早期的定義」(或早期初始化)功能:

class Y extends { 
    var s = "Hello" 
} with X { 
    def a: Unit = println ("String is "+s) 
} 
+0

我需要's'是一個'var'因爲它後來被修改在我的代碼。因此,'def'和'val'都不起作用。 – Jus12 2011-04-22 13:44:57

+0

謝謝。早期定義功能很有趣。 – Jus12 2011-04-22 13:59:28

+0

你可以退後一步,多說你想做什麼,而不是你想做什麼? – 2011-04-22 13:59:48