2010-09-30 45 views
15

請看下面的代碼。斯卡拉初始化行爲

trait MyTrait { val myVal : String } 

class MyClass extends MyTrait { val myVal = "Value" } 

class MyClass2(val myVal: String) extends MyTrait 

爲什麼初始化訂購MyClassMyClass2情況有什麼不同? 的MyClass構造將作爲

MyClass() { 
    MyTrait$class.$init$(this); 
    myVal = value 
} 

MyClass2構造將是

MyClass2(String myVal) { this.myVal = myVal; MyTrait$class.$init$(this) } 

我覺得初始化順序應爲MyClass2的構造函數,同樣的兩種情況。

回答

23

Scala specification的5.1節的末尾,下面的定義:

模板評價。考慮一個模板sc mt 1 mt n {stats}。如果這是 特徵(第5.3.3節)的模板,則其混合評估由語句序列 stats的eval- 組成。如果這不是 特徵的模板,則其評估包括 以下步驟。

  • 首先,評估超類構造函數sc(§5.1.1)。
  • 然後,模板的線性化(§5.1.2)中的所有基類增加 到模板的超類,由sc表示爲 sc是mixin評估的。 Mixin評估發生在 線性化中的發生順序 。
  • 最後對語句序列統計進行評估。

但是,請注意,構造函數參數可以由任何後面的構造函數使用。因此,需要在它們之前進行初始化。這是在第5.1.1節的結束作出了明確:

構造函數調用 x.c targs的評價。 。 。 (argsn)包括以下 步驟:

  • 首先,前綴X進行評價。
  • 然後,參數args1,。 。 。 ,argsn評估從左到右 權利。
  • 最後,通過評估 c所指的類別的 模板來初始化正在構建的類別。

這你沒有任何問題,但你有{}統計正在最後執行的問題。 {stats}最後執行的原因是它可能引用其祖先類和特徵的屬性,而祖先顯然不知道它的後代。因此,在執行{stats}之前,祖先需要完全初始化。

當然,有可能你需要提前初始化。這由第5.1.6節「早期定義」涵蓋。下面是你如何寫它:

class MyClass extends { val myVal = "Value" } with MyTrait 
+0

最終我看到了爲什麼Scala初始化一個對象的原因。謝謝你的回答,丹尼爾。 – Dmitry 2010-10-01 14:04:46