2013-08-21 12 views

答えて

10

まあまあ正しいです。もし形質Fooを定義するとき

、それはフードの下(JVM)インターフェースFoo及び静的メソッドとして定義されているすべてのメソッドの実装と(JVM)クラスFoo$classの両方を作成します。 、あなたは具体的なクラスBarFooを混ぜるとき

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

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

は、JVMレベルで何が起こるかBarインターフェイスFooを拡張することです:対応するJavaコードは(Fooの新しいdefintionのため)このようなもののようになります。そして、それは単にFoo$classにコールを転送することによって方法verifyConsistencyを実装しています

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

それがこのように行われている理由は、JVMのオブジェクトモデルが多重継承をサポートしていないということです。 JVM上で単一のクラスを拡張することができるだけであるため、特性実装は、拡張するクラスに単純に配置することはできません。

具体的なクラスが特性を混合するたびに、クラスは特性の各メンバー(静的メソッドである実際の実装に単純に転送するメソッド)に「スタブ」メソッドを定義します。

結果として、新しいメソッドを特性に追加すると、実装を定義しても、特性を混合する具体的なクラスが再コンパイルする必要があります(新しいメソッドのスタブが追加されるクラスに)。これらのクラスを再コンパイルしないと、具体的な(抽象的ではない)クラスが作成され、対応するインタフェースが拡張されますが、実際には新しいメソッドの実装が見付かりません。

これは、インターフェイスFooを拡張する具体的なクラスを持つことを意味しますが、verifyConsistencyの実装はありません。

したがって、バイナリの非互換性。

+1

ありがとうございました。私は、特性を取り巻く全体的な儀式は、メソッドを追加できると思っていました。あなたがデフォルトの実装を提供する限り、すべてを再コンパイルする必要はありません。だから私はそこに間違っていたと思う:-( –

関連する問題