2016-06-10 58 views
2

我在斯卡拉有關性狀的繼承

class MI { 
    def identity : Int = { 
     println("came inside MI") 
     1 
    } 
} 

trait DMI extends MI { 
    override def identity : Int = { 
     println("came inside DMI") 
     2 * super.identity 
    } 
} 

trait TMI extends MI { 
    override def identity : Int = { 
     println("came inside TMI") 
     3 * super.identity 
    } 
} 

class Foo extends TMI with DMI { 
    override def identity : Int = super[DMI].identity 
} 

val f = new Foo 
f.identity 

寫這段代碼的代碼的輸出混亂是

came inside DMI 
came inside TMI 
came inside MI 
res5: Int = 6 

誰能解釋爲什麼呼叫TMI裏面去?根據我的答案應該是2

+1

閱讀:http://www.artima.com/scalazine/文章/ stackable_trait_pattern.html – Dima

回答

2

這裏使用的是可堆疊行爲。當Scala遇到new時,它會對類進行線性化。這線性決定遇到super時方法在鏈將被調用。爲了您例如,Foo線性化將是這樣的:

Foo -> DMI -> TMI -> MI -> AnyRef -> Any 

所以如果super在任何方法的遭遇,實施將從右到左被拾起。

  • 首先,它執行從DMIidentity(因爲你已經明確地使用super[DMI] 線性化將不使用),這也有super.identity和 按線性化:在這種情況下,由於super[DMI].identityidentity方法Foo使用
  • 它執行從TMI,這又具有super.identity identity和按照線性
  • 它執行identityMI

這就是爲什麼你6作爲最終的輸出。

,如果您已經從裏面Foo稱爲super[TMI].identity,結果將是3

您可以參考有關線性化的詳細信息this鏈接。

1

FOO的結構如下:

  1. TMI與DMI {美孚}

  2. 展開全部類型,直到你與MI與達成任何

(任何與AnyRef TMI)與(任何與MI與DMI AnyRef)與{}富

  • 移動由左到右,刪除所有重複
  • 含{富}

    (任何與AnyRef與MI與TMI)與(DMI)

  • 下面是所得類型。現在,從右側開始,檢查有「super'behaves
  • 任何與AnyRef與MI與TMI與DMI與{}富