3

問題:

Java が複数のクラスを拡張することを許可していないことはわかっています。これは、コンパイラがどのスーパークラス メソッドを使用するかを決定できなくなるダイヤモンド問題が発生するためです。インターフェイスのデフォルト メソッドでは、ダイヤモンド問題がJava 8で導入されました。つまり、クラスが 2 つのインターフェイスを実装し、それぞれが同じ既定のメソッドを定義し、実装するクラスが共通の既定のメソッドをオーバーライドしない場合、コンパイラはどちらの実装を選択するかを決定できなかったからです。

解決:

Java 8では、複数のインターフェースによって実装されるデフォルト メソッドの実装を提供する必要があります。したがって、クラスが上記の両方のインターフェースを実装する場合、共通のデフォルト メソッドの実装を提供する必要があります。そうしないと、コンパイラはコンパイル時エラーをスローします。

質問:

子クラスによって導入された共通メソッドをオーバーライドすることにより、このソリューションが複数クラスの継承に適用されないのはなぜですか?

4

3 に答える 3

1

インターフェイスによって導入されたメソッドは常にオーバーライドされる可能性がありますが、クラスによって導入されたメソッドは最終的なものになる可能性があります。これが、インターフェイスに適用できるのと同じ戦略をクラスに適用できない可能性がある理由の 1 つです。

于 2016-12-21T09:29:48.610 に答える
0

「ダイアモンドの問題」と呼ばれる競合A.m()は、レシーバーの実行時の型が type を持つメソッドへのDポリモーフDィック呼び出しを使用して最もよく説明A.m()できますA.m()。それらの少なくとも 1 つはオーバーライドです)。現在、動的ディスパッチは、競合するメソッドのどれを呼び出すかを決定できません。

余談ですが、「ダイヤモンド問題」と通常の名前の競合の違いは、たとえば 1 つのメソッドの名前を変更するなどして、type の観点からローカルに競合を解決できる Eiffel のような言語に特に関連しています。これにより、 static type での呼び出しの名前衝突は回避されますが、 static typeでの呼び出しでは回避されませんDDA

現在、Java 8 のデフォルト メソッドを使用して、JLS はそのような競合を検出するルールで修正されD、競合を解決する必要があります (関連する型の一部がクラスであるかどうかに応じて、さまざまなケースが存在します)。つまり、ダイヤモンドの問題は Java 8 では「解決」されておらず、それを生成するプログラムを拒否することで回避されているだけです。

理論的には、Java 1 で同様の規則を定義して、クラスの多重継承を許可することができたはずです これは、Java の設計者が多重継承をサポートしたくないという早い段階での決定にすぎません。

クラス メソッドではなく、デフォルト メソッドの複数の (実装) 継承を許可するという選択は、純粋に実用的な選択であり、理論によって必要とされるものではありません。

于 2016-12-22T10:11:45.477 に答える