source

같은 방식의 클래스 내 2개의 인터페이스를 실장한다.어떤 인터페이스 방식이 재정의됩니까?

goodcode 2022. 9. 23. 00:12
반응형

같은 방식의 클래스 내 2개의 인터페이스를 실장한다.어떤 인터페이스 방식이 재정의됩니까?

메서드 이름과 시그니처가 같은2개의 인터페이스그러나 단일 클래스에서 구현되는 경우 컴파일러는 어떤 메서드가 어떤 인터페이스인지 어떻게 식별합니까?

예:

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;
  }
}   

를 실장하고 있으며, 각 타입이 2개의 인터페이스를 실장하고 있는 ,interface동일한 시그니처를 가진 메서드를 정의합니다.실제로 메서드는 1개뿐이며 구분할 수 없습니다.예를 들어 두 메서드의 반환 유형이 충돌하는 경우 컴파일 오류가 발생합니다.의 「」, 「」, 「」, 「」의 에 발생할 가능성이 .interface도 .interface 슈퍼 ★★★★★★★★★★★★★★★★★.class또는 제네릭의 활자 삭제로 인한 충돌일 수도 있습니다.


호환성 예시

를 들어, 이 에서는 '예', '예', '예', '예', '예', '예', '예', '예', '예', '예', '예', '예', '예'가 있습니다.interface Gift에는)가 .present() 선물하기) 및 예: 선물하기)도 있습니다.interface Guest에는)도 .present()method(예:게스트는 존재하지만 존재하지 않습니다).

Presentable johnny망원경은 둘 다이다Gift그리고 싱크는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!!!"
    }
}

위의 스니펫은 컴파일하여 실행합니다.

1개뿐이라는 점에 주의해 주십시오. @Override 필요!!!그 이유는Gift.present()그리고 그리고.Guest.present()있""@Override- 등가" (JLS 8.4.2).

따라서, 따라서,johnny 의 실장은 1개뿐입니다present()그리고 이것은 여러분이 치료하는지 그리고 당신이 어떻게 대하는지는 중요하지 않다 중요하지 않다.johnny, 등은 으로서도Gift혹은 또는 로서Guest오직 하나 메서드를 호출하는 것이다.호출하는 메서드는 1개뿐입니다.


비호환성 예시

다음 예에서는 상속된 두 가지 방법이 다른 방법을 보여 줍니다.@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회원 선언의 일반적인 규칙을 준수해야 한다., 여기 있습니다.Gift ★★★★★★★★★★★★★★★★★」Guestpresent()되지 않는 반환 1 " " " " " " " " : 1 " 1voidboolean같은 이유로, 당신이 할 수 없는 것은void present() a. a. a.boolean present()이 예에서는 컴파일 오류가 발생합니다.


요약

하다, 하다, 하다, 하다, 하다, 하다, 하는 방법들을 수 .@Override-불일치, 메서드 덮어쓰기 및 숨김의 통상적인 요건에 따릅니다.그들이 있기 때문에 @Override- 일관성이 있습니다.실행할 수 있는 방법은 1개뿐이기 때문에 구별하거나 선택할 필요가 없습니다.

.이 어떤 하면 됩니다.왜냐하면 컴파일러가 어떤 인터페이스용인지 결정되면@Override같은 수법입니다.

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

레퍼런스

이것은 이 질문의 중복으로 표시되어 있습니다.https://stackoverflow.com/questions/24401064/understanding-and-solving-the-diamond-problems-in-java

다중 상속 문제가 발생하려면 Java 8이 필요하지만 여전히 diamon 문제가 아닙니다.

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.

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

이 두 가지 방법이 실질적으로 동일하다면 동일한 구현을 가져야 한다는 점에서 문제가 되지 않습니다.(각 인터페이스의 매뉴얼에 따라) 계약상 다를 경우 문제가 발생합니다.

식별할 수 있는 것은 아무것도 없습니다.인터페이스는 메서드 이름과 시그니처만 금지합니다.양쪽 인터페이스의 이름과 시그니처가 완전히 같은 메서드를 사용하는 경우 구현 클래스는 하나의 구체적인 메서드로 두 인터페이스 메서드를 구현할 수 있습니다.

단, 2개의 인터페이스 메서드의 시멘틱컨트랙트가 모순되는 경우는 거의 손실입니다.그때, 1개의 클래스로 양쪽의 인터페이스를 실장할 수 없습니다.

인터페이스와 마찬가지로 메서드를 선언하고 있습니다.이러한 양쪽 인터페이스를 실장하는 구체적인 클래스는 메서드는 1개뿐입니다(양쪽 모두 반환 타입에 같은 이름을 가지고 있습니다).문제가 없을 겁니다.당신은 구체적인 수업에서 그 방법을 정의할 수 있을 것입니다.

단, 2개의 인터페이스에 이름이 같지만 반환 타입이 다른 메서드가 있으며 구체적인 클래스에서2개의 메서드를 실장하고 있는 경우:

아래 코드를 참조해 주세요.

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()"를 취득하면 먼저 인터페이스A를 검색하여 취득합니다.그러나 반환 유형이 인터페이스 B의 메서드와 호환되지 않는다는 컴파일 시간 오류가 발생합니다.

컴파일러에 문제가 생겼군요.

이 방법으로는 이름이 같지만 반환 유형이 다른2개의 인터페이스를 구현할 수 없습니다.

둘 다 같다면 상관없습니다.인터페이스 방식당 하나의 구체적인 방법으로 둘 다 구현합니다.

인터페이스를 어나니머스로서 실장해 주세요.

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(){

}

}

두 가지 방법을 모두 구현하고 모호성을 피하기 위해 다음 두 가지 접근방식을 사용할 수도 있습니다.

접근법 1:

App.java-

public class App {
    public static void main(String[] args) {
        TestInterface1 testInterface1 = new TestInterface1();
        TestInterface2 testInterface2 = new TestInterface2();
        testInterface1.draw();
        testInterface2.draw();
    }
}

TestInterface1.java-

public class TestInterface1 implements Circle {
    
}

TestInterface2.java-

public class TestInterface2 implements Rectangle {
    
}

Circle.java-

public interface Circle extends Drawable {
    @Override
    default void draw() {
        System.out.println("Drawing circle");
    }
}

Rectangle.java-

public interface Rectangle extends Drawable {
    @Override
    default void draw() {
        System.out.println("Drawing rectangle");
    }
}

Drawable.java-

public interface Drawable {
    default void draw() {
        System.out.println("Drawing");
    }
}

출력 -

Drawing circle
Drawing rectangle

어프로치 2:

App.java-

public class App {
    public static void main(String[] args) {
        
        Circle circle = new Circle() {
                
        };
        Rectangle rectangle = new Rectangle() {
                
        };

        circle.draw();
        rectangle.draw();
    }
}

Circle.java-

public interface Circle extends Drawable {
    @Override
    default void draw() {
        System.out.println("Drawing circle");
    }
}

Rectangle.java-

public interface Rectangle extends Drawable {
    @Override
    default void draw() {
        System.out.println("Drawing rectangle");
    }
}

Drawable.java-

public interface Drawable {
    default void draw() {
        System.out.println("Drawing");
    }
}

출력 -

Drawing circle
Drawing rectangle

언급URL : https://stackoverflow.com/questions/2801878/implementing-two-interfaces-in-a-class-with-same-method-which-interface-method

반응형