私たちは皆、多重継承に関して ダイヤモンドの問題 について知っています-
A
/ \
B C
\ /
D
この問題は、クラスD
のあいまいな状況を説明しています。クラスA
にメソッドがあり、B
とC
の両方またはいずれかがメソッドをオーバーライドする場合、どのバージョンのメソッドがD
をオーバーライドしますか?
この問題はJavaのインターフェースにも当てはまりますか?そうでない場合、どのようにJavaインターフェースがこの問題を克服しますか?
ひし形の問題は実装継承(extends
Java以前のJava 8)のみ)にのみ適用されます。[〜#〜] api [〜#〜]継承(implements
Java以前の= Java 8)。
タイプシグネチャが一致するインターフェースメソッドは互換性があるため、同じメソッドシグネチャを2回継承しても、ダイアモンドの問題はありません。一致するメソッドシグネチャは、代わりに単に合体します。 (そして、型シグネチャが同じでなければ、ひし形の問題もありません。)
Java 7以下では、implementationコードを継承する唯一の方法は、extends
キーワードを使用することでしたが、これは最大で1つの親に制限されています。多重実装継承ではなく、ひし形の問題は存在しません。
Java 8では、インターフェースに実装コードを含めることができるため、新しいしわが追加されています。一致するシグネチャを持つメソッドを持つ複数のインターフェースを実装する場合、以前の動作(実装の継承なし)にフォールバックするだけで、ひし形の問題を回避できます。
デフォルトの実装はunambiguous(クラスA
の1つ)または状況はいくつかのルールによって解決されます(クラスB
またはクラスC
がクラスA
からの実装をオーバーライドする場合、以下を参照)。
クラスまたはインターフェイスのスーパータイプが、同じシグネチャを持つ複数のデフォルトメソッドを提供する場合:
ただし、2つ以上の独立して定義されたデフォルトメソッドが競合する場合、またはデフォルトメソッドが抽象メソッドと競合する場合、Javaコンパイラはコンパイラを生成します。エラーは、スーパータイプメソッドを明示的にオーバーライドする必要があります。この場合、superキーワードを使用して、デフォルト実装のいずれかを呼び出すことができます。
参照: Java 8 '新しいデフォルトのインターフェースモデルはどのように機能しますか(ダイヤモンド、多重継承、優先順位を含む)?
Java 8で導入されたインターフェースのデフォルトメソッドでは、多重継承に関連する問題が発生する可能性があります。3つのシナリオがあります-
1-実装クラスがデフォルトメソッドをオーバーライドし、デフォルトメソッドに独自の機能を提供する場合、クラスのメソッドはインターフェースのデフォルトメソッドよりも優先されます。
2-クラスが両方のインターフェイスを実装し、両方に同じデフォルトのメソッドがある場合、クラスはそのメソッドをオーバーライドしていないため、エラーがスローされます。
3-インターフェイスが別のインターフェイスを拡張し、両方に同じデフォルトメソッドがある場合、継承するインターフェイスのデフォルトメソッドが優先されます。
それについてもっと読む ここ 。
Javaは多重継承をサポートしていないため、ひし形の問題は発生しません。 B&Cがインターフェースの場合、インターフェースには実装がありません。 BとCがインターフェースAのメソッドをオーバーライドしても(クラスにすることはできません)、メソッドは同じ署名を持ちます。実装がないため、どの実装を使用するかについてのあいまいさはありません。
ダミー宣言を持つインターフェースには実装がないため、あいまいさの問題はありません。