2つのJavaインターフェイスと1つの実装クラスがあります。
(私はEclipseを使用してプログラムを直接実行しましたが、コマンドラインから明示的にコンパイルしてコンパイラの警告などを確認しようとはしませんでした。)
なぜ問題なく動作するのですか? Javaは、両方のインターフェイスの「コントラクト」を満たしているが、クラスの実装にあいまいさを生じさせている場合でも、これを許可するのはなぜですか?
例を更新しました。
public interface CassettePlayer {
void play();
}
public interface DVDPlayer {
void play();
}
public class CarPlayer implements CassettePlayer,DVDPlayer{
@Override
public void play() {
System.out.println("This plays DVD, screw you Cassette !");
}
public static void main(String args[]) {
CarPlayer cp = new CarPlayer();
cp.play();
CassettePlayer firstInterface = new CarPlayer();
firstInterface.play();
DVDPlayer secondInterface = new CarPlayer();
secondInterface.play();
}
}
このシナリオは、 Java言語仕様、セクション8.1.5 で特に許可されています。
クラス内の単一のメソッド宣言で、複数のスーパーインターフェイスのメソッドを実装することは許可されています。たとえば、コードでは次のようになります。
interface Fish { int getNumberOfScales(); } interface Piano { int getNumberOfScales(); } class Tuna implements Fish, Piano { // You can tune a piano, but can you tuna fish? int getNumberOfScales() { return 91; } }
クラス
getNumberOfScales
のメソッドTuna
には、インターフェイスFish
で宣言されたメソッドと一致し、インターフェイスPiano
;両方を実装すると見なされます。
次に、メソッドシグネチャの戻り値の型がdouble
とint
のように異なる場合、両方のインターフェイスを同じクラスとコンパイル時間で実装する方法はないことに注意してください。エラーが発生します。
この問題では、インターフェイスの目的を理解する必要があります。
インターフェイスは一種の「コントラクト」であるため、そのインターフェイスを使用してクラスに強制的に実装されているメソッドを知ることができます。
したがって、「DVDPlayer」を実装するクラスが必要な場合(メソッド「play()」が必要なため)、CarPlayerが見つかります。カセットプレーヤーを実装するクラスの必要性についても同じことが言えます。それが技術的な説明です。
ただし、もちろん、セマンティックコーディングでは、CarPlayerのメソッド「play()」がDVDPlayerとCassettePlayerの両方のセマンティクスを満たしていることを確認する必要があります。実際のアプリケーションでは、それは悪い習慣になると思います。
もちろん、あなたの例では、同じメソッドを宣言する2つのインターフェースを持つことは悪い考えです。より実際的には、メソッド「play()」を使用してインターフェイス「Player」を作成し、Playerから継承する2つのより具体的なインターフェイスDVDPlayerとCassettePlayer(DVDとカセット用の特定のメソッドを使用)を用意する必要があります。一方、DVDまたはカセットに特定のメソッドが必要ない場合は、1つの同じメソッドを実装するだけの2つの異なるインターフェイスは必要ありません。1つのインターフェイスPlayerを使用するだけで十分です。
この状況では、両方のインターフェイスが同じメソッドシグネチャを持っているため、問題はありません。しかし、これはどうですか?
interface Animal {
public void eat() throws IOException;
}
interface Plants {
public void eat() throws NullPointerException;
}
どちらがコンパイラによって選択されますか?コードの下でエラーが発生するのはなぜですか?
public class Test implements Animal, Plants {
public void eat() throws IOException {
}
}
コンパイラによると:例外IOExceptionはPlants.eat()のthrows句と互換性がありません
次のページには、次の2つのインターフェイスを実装するクラスの例が含まれています。
1)同じ変数名2)各インターフェースで同じメソッド。
http://www.j2eeonline.com/Java-tm-fundamentals-II/module2/interface-ambiguous-fields.jsp
どちらも同じコントラクトを指定しているため、競合はありません。実装クラスは、いずれかのインターフェイスを介して参照されたときに呼び出される1つのメソッドのみを提供します。
何故なの?このクラスは、両方のインターフェースで定義されたコントラクトを満たしています。
このクラスは両方のインターフェースを実装しているため、問題はありません。もちろん、この種のことは、意図しない動作が発生する可能性があるより複雑なシナリオでは回避する必要があります。