3
interface CanFight {
  void fight();
}

interface CanSwim {
  void swim();
}

interface CanFly {
  void fly();
}

class ActionCharacter {
  public void fight() {
      System.out.println("Inside class fight");
  }
}

class Hero extends ActionCharacter
    implements CanFight, CanSwim, CanFly {
  public void swim() {}
  public void fly() {}
}

      public class MultipleInterface {
  public static void t(CanFight x) { x.fight(); }
  public static void u(CanSwim x) { x.swim(); }
  public static void v(CanFly x) { x.fly(); }
  public static void w(ActionCharacter x) { x.fight(); }
  public static void main(String[] args) {
    Hero h = new Hero();
    t(h); // Treat it as a CanFight
    u(h); // Treat it as a CanSwim
    v(h); // Treat it as a CanFly
    w(h); // Treat it as an ActionCharacter
  }
}

canFightインターフェイスからメソッドを実装していないのに、ActionCharacterクラスからメソッドを取得しているため、JVMはどのように動作しますか?その背後にあるロジックは何ですか?ポイントは、インターフェースをfight()実装する場合に実行しなければならないメソッドを定義していないということです。canFight()

4

5 に答える 5

3

これはJVMではなく、Javaコンパイラです。(JVMが、存在するはずのメソッドが欠落していることを検出すると、NoSuchMethodExceptionが発生しますが、コンパイラーは、それをだまさない限り、そのポイントに到達することを許可しません)。

あなたの質問に関しては、メソッドがどのクラス、スーパークラス、またはインターフェースで宣言されているかは関係ありません。名前と署名だけが一致する必要があります。したがって、同じことActionCharacter#fightCanFight#fight宣言します。Javaは、この2つを区別しません(コンパイラーもJVM /バイトコード形式も区別しません)。

からHero継承fightActionCharacterますが、で定義されたメソッドとも一致するCanFightため、そのインターフェイスの実装としても機能します。

メソッド名を変更する(2つの異なるメソッドであると想定される場合)か、ActionCharacter実装するCanFight(これが実際に同じメソッドであることが意図されている場合)のがより明確になる可能性があります。

于 2013-03-25T06:19:20.097 に答える
2

タイプが2つのインターフェースを実装し、各インターフェースが同一のシグニチャーを持つメソッドを定義する場合、実際には1つのメソッドしかなく、それらは区別できません。

たとえば、2つのメソッドの戻り型が競合している場合は、コンパイルエラーになります。これは、継承、メソッドのオーバーライド、非表示、および宣言の一般的なルールであり、2つの継承されたインターフェイスメソッド間だけでなく、インターフェイスとスーパークラスメソッド間で発生する可能性のある競合、またはジェネリックの型消去による競合にも適用されます。 。

JLSで言われています

クラス内の単一のメソッド宣言で、複数のスーパーインターフェイスのメソッドを実装することは許可されています。

于 2013-03-25T06:30:50.357 に答える
1

拡張ActionCharacterしています。つまり、のすべての操作と属性をクラスにActionCharacter継承する必要があります。Hero

これにはfight操作も含まれます。Hero実装としてマークしますCanFightが、実際の実装をから継承しますActionCharacter

于 2013-03-25T06:18:26.073 に答える
0

Heroは実装する必要がありますが、ActionCharacterからvoid figth();継承するため、要件が満たされます。void figth();

于 2013-03-25T06:24:35.303 に答える
0

インターフェイスはメソッドを宣言するだけであり、インターフェイスでメソッドを定義することはできません。つまり、インターフェースに実装したいもののドラフトを提供するということです。

ここで、クラスHeroは、public void fight()の定義を持つクラスActionCharacterを継承します。ただし、このfight()はCanFightのfight()とは関係ありません。したがって、Heroでfight()を定義すると、ActionCharacterのfight()がオーバーライドされます。

インターフェースCanFightも実装しているため、CanFightでメソッドを宣言したので、jvmはこれを許可しますが、ActionCharacterのfight()のオーバーライドとして扱われます。

于 2013-03-25T06:27:23.250 に答える