[java] 동일한 메소드를 사용하여 클래스에서 두 개의 인터페이스를 구현합니다. 어떤 인터페이스 방법이 재정의됩니까?

메소드 이름과 서명이 동일한 두 개의 인터페이스. 그러나 단일 클래스로 구현되면 컴파일러가 어떤 인터페이스가 어떤 인터페이스인지 식별하는 방법은 무엇입니까?

전의:

interface A{
  int f();
}

interface B{
  int f();
}

class Test implements A, B{
  public static void main(String... args) throws Exception{

  }

  @Override
  public int f() {  // from which interface A or B
    return 0;
  }
}   



답변

유형이 두 개의 인터페이스를 구현하고 각각 interface동일한 서명을 가진 메소드를 정의하는 경우 실제로는 하나의 메소드 만 있으며 구별 할 수 없습니다. 예를 들어 두 메소드가 리턴 유형이 충돌하면 컴파일 오류가됩니다. 이것은 상속, 메소드 재정의, 숨기기 및 선언의 일반적인 규칙이며, 상속 된 두 interface메소드뿐만 아니라 interface슈퍼 class메소드 사이의 가능한 충돌에도 적용 되거나 제네릭의 유형 삭제로 인한 충돌에도 적용됩니다.


호환성 예

여기에 (선물을 제시하는 것과 같은) 방법 interface Gift이있는 present()및가 있는 예가 interface Guest있습니다.present() (, 게스트가없는 현재와하지에로) 방법을.

Presentable johnnya Gift와 a Guest입니다.

public class InterfaceTest {
    interface Gift  { void present(); }
    interface Guest { void present(); }

    interface Presentable extends Gift, Guest { }

    public static void main(String[] args) {
        Presentable johnny = new Presentable() {
            @Override public void present() {
                System.out.println("Heeeereee's Johnny!!!");
            }
        };
        johnny.present();                     // "Heeeereee's Johnny!!!"

        ((Gift) johnny).present();            // "Heeeereee's Johnny!!!"
        ((Guest) johnny).present();           // "Heeeereee's Johnny!!!"

        Gift johnnyAsGift = (Gift) johnny;
        johnnyAsGift.present();               // "Heeeereee's Johnny!!!"

        Guest johnnyAsGuest = (Guest) johnny;
        johnnyAsGuest.present();              // "Heeeereee's Johnny!!!"
    }
}

위의 스 니펫은 컴파일되고 실행됩니다.

참고 하나가 @Override 필요합니다! . 이 때문입니다 Gift.present()Guest.present()“이다 @Override(-equivalent” JLS 8.4.2 ).

따라서의 johnny 구현하나만 있으며 a로 또는 a 로 present()처리하는 방법은 중요하지 않습니다 . 호출 할 메소드는 하나뿐입니다.johnnyGiftGuest


비 호환성 예

다음은 상속 된 두 메소드가 동일하지 않은 예입니다 @Override.

public class InterfaceTest {
    interface Gift  { void present(); }
    interface Guest { boolean present(); }

    interface Presentable extends Gift, Guest { } // DOES NOT COMPILE!!!
    // "types InterfaceTest.Guest and InterfaceTest.Gift are incompatible;
    //  both define present(), but with unrelated return types"
}

이것은 또한 멤버로부터 상속받는 멤버 interface가 멤버 선언의 일반적인 규칙을 준수해야 함을 반복합니다 . 여기에서 우리는이 GiftGuest정의 present()호환되지 않는 반환 형식으로 하나 void다른 boolean. 같은 이유로 당신은 할 수 없다는 void present()하고 boolean present()한 가지 유형에서, 컴파일 오류이 예의 결과.


요약

@Override메서드 재정의 및 숨기기의 일반적인 요구 사항에 따라 동등한 메서드를 상속 할 수 있습니다 . 그들은 이후 내용입니다 @Override -equivalent 효과적으로 구현하는 하나의 방법이있다, 따라서 선택 / 구별 할 것도 없다.

컴파일러는 일단 어떤 인터페이스가 어떤 인터페이스인지 결정하지 않아도됩니다. @Override 동일한 되면 동일한 메소드 입니다.

잠재적 인 비 호환성을 해결하는 것은 까다로운 작업 일 수 있지만 이는 또 다른 문제입니다.

참고 문헌


답변

이것은이 질문에 중복으로 표시되었습니다 /programming/24401064/understanding-and-solving-the-diamond-problems-in-java

다중 상속 문제를 얻으려면 Java 8이 필요하지만 여전히 그러한 문제는 아닙니다.

interface A {
    default void hi() { System.out.println("A"); }
}

interface B {
    default void hi() { System.out.println("B"); }
}

class AB implements A, B { // won't compile
}

new AB().hi(); // won't compile.

JB Nizet가 언급 했듯이이 문제를 해결할 수 있습니다.

class AB implements A, B {
    public void hi() { A.super.hi(); }
}

그러나, 당신은 문제가 없습니다

interface D extends A { }

interface E extends A { }

interface F extends A {
    default void hi() { System.out.println("F"); }
}

class DE implement D, E { }

new DE().hi(); // prints A

class DEF implement D, E, F { }

new DEF().hi(); // prints F as it is closer in the heirarchy than A.


답변

컴파일러에 관한 한이 두 가지 방법은 동일합니다. 두 가지 모두 한 가지 구현이있을 것입니다.

두 메소드가 동일한 구현을 가져야한다는 점에서 두 메소드가 효과적으로 동일한 경우에는 문제가되지 않습니다. 계약이 다르면 (각 인터페이스의 설명서에 따라) 문제가 생길 수 있습니다.


답변

식별 할 것이 없습니다. 인터페이스는 메소드 이름과 서명 만 제공합니다. 두 인터페이스 모두 정확히 동일한 이름과 서명의 메소드를 갖는 경우, 구현 클래스는 하나의 구체적 메소드로 두 인터페이스 메소드를 모두 구현할 수 있습니다.

그러나 두 인터페이스 방법 의 의미 적 계약이 모순되는 경우 거의 손실 된 것입니다. 그러면 단일 클래스에서 두 인터페이스를 모두 구현할 수 없습니다.


답변

익명으로 인터페이스를 구현하십시오.

public class MyClass extends MySuperClass implements MyInterface{

MyInterface myInterface = new MyInterface(){

/* Overrided method from interface */
@override
public void method1(){

}

};

/* Overrided method from superclass*/
@override
public void method1(){

}

}


답변

인터페이스에서와 같이 우리는 단지 메소드를 선언하고 있습니다.이 두 인터페이스를 모두 구현하는 콘크리트 클래스는 하나의 메소드 만 있다는 것을 이해합니다 (둘 다 리턴 유형에서 동일한 이름을 가짐). 문제가 없어야합니다. 구체적인 클래스에서 해당 메소드를 정의 할 수 있습니다.

그러나 두 개의 인터페이스가 이름은 같지만 리턴 유형이 다른 메소드를 가지고 있고 구체적인 클래스에서 두 가지 메소드를 구현 한 경우 :

아래 코드를보십시오 :

public interface InterfaceA {
  public void print();
}


public interface InterfaceB {
  public int print();
}

public class ClassAB implements InterfaceA, InterfaceB {
  public void print()
  {
    System.out.println("Inside InterfaceA");
  }
  public int print()
  {
    System.out.println("Inside InterfaceB");
    return 5;
  }
}

컴파일러가 “public void print ()”메소드를 가져 오면 먼저 InterfaceA를 찾아서 가져옵니다. 그러나 여전히 리턴 유형이 InterfaceB의 메소드와 호환되지 않는 컴파일 시간 오류가 발생합니다.

그래서 컴파일러를 위해 haywire로갑니다.

이런 방식으로 이름은 같지만 리턴 유형이 다른 메소드를 갖는 두 개의 인터페이스를 구현할 수 없습니다.


답변

둘 다 같으면 문제가되지 않습니다. 인터페이스 방법마다 하나의 구체적인 방법으로 두 가지를 모두 구현합니다.