2013-08-21 24 views

回答

10

嗯是的,它是正確的。

當您定義特徵Foo時,它將在全部方法實現中定義爲靜態方法的同時創建(JVM)接口Foo和(JVM)類Foo$class。相應的Java代碼看起來像這樣的事情(爲您的新的Foo確定指標):

interface Foo { 
    Option<String> verifyConsistency(); 
} 

class Foo$class { 
    static Option<String> verifyConsistency(Foo self) { 
    Predef.???(); 
    } 
} 

當您混合Foo到一個具體的類Bar,JVM級別發生的事情是Bar擴展接口Foo,並通過簡單的轉發調用Foo$class實現方法verifyConsistency

class Bar implements Foo { 
    Option<String> verifyConsistency() { 
    return Foo$class.verifyConsistency(this); // simple forwarding 
    } 
} 

爲什麼做這樣的原因是JVM對象模型不支持多重繼承。特性實現不能簡單地放在你可以擴展的類中,因爲你只能在JVM上擴展一個類。

這種情況的影響是,每當一個具體類混合一個特質時,該類爲特徵的每個成員(這些方法簡單地轉發給實際實現,這是一種靜態方法)定義「存根」方法。

其中一個結果是,如果向特徵添加新方法,即使定義了實現,也是不夠的:混合特徵的具體類需要重新編譯(以便添加新方法的存根到班級)。如果您不重新編譯這些類,那麼程序將無法運行,因爲您現在將擁有一個類似於具體(非抽象)的類,並且擴展了相應的接口,但實際上錯過了新方法的實現。

在你的情況下,這意味着具有擴展接口Foo的具體類,但沒有verifyConsistency的任何實現。

因此二進制不兼容。

+1

好的謝謝。我認爲整個儀式的特點是你可以添加方法,只要你提供一個默認實現,你不必重新編譯所有東西。所以我想我錯了:-( –