인터페이스 - 다중구현
자바가 다중 상속을 지원하지 않는 이유 - 복습
자바는 다중 상속을 지원하지 않습니다.
그래서 extend 대상은 하나만 선택할 수 있습니다.
- 부모를 하나만 선택할 수 있다는 뜻입니다.
- 물론 부모가 또 부모를 가지는 것은 괜찮습니다.

만약 비행기와 자동차를 상속 받아서 하늘을 나는 자동차를 만든다고 가정해봅시다.
만약 그림과 같이 다중 상속을 사용하게 되면 AirplaneCar 입장에서 move()를 호출할 때 어떤 부모의 move()를 사용해야 할지 애매한 문제가 발생합니다.
- 이것을 다이아몬드 문제라 합니다.
그리고 다중 상속을 사용하면 클래스 계층 구조가 매우 복잡해질 수 있습니다.
이런 문제점 때문에 자바는 클래스의 다중 상속을 허용하지 않습니다.
- 대신에 인터페이스의 다중 구현을 허용하여 이러한 문제를 피합니다.
클래스는 앞서 설명한 이유로 다중 상속이 안되는데, 인터페이스의 다중 구현은 허용한 이유는 무엇일까요?
- 인터페이스는 모두 추상 메서드로 이루어져 있기 때문입니다.
다음 예제를 봅시다.

InterfaceA, InterfaceB는 둘 다 같은 methodCommon()을 가지고 있습니다.
그리고 Child는 두 인터페이스를 구현했습니다.
- 상속 관계의 경우 두 부모 중에 어떤 한 부모의
methodCommon()을 사용해야 할지 결정해야 하는 다이아몬드 문제가 발생합니다.- 하지만 인터페이스 자신은 구현을 가지지 않습니다.
- 대신에 인터페이스를 구현하는 곳에서 해당 기능을 모두 구현해야 합니다.
- 하지만 인터페이스 자신은 구현을 가지지 않습니다.
여기서 InterfaceA, InterfaceB는 같은 이름의 methodCommon()를 제공하지만 이것의 기능은 Child가 구현합니다.
- 그리고 오버라이딩에 의해 어차피
Child에 있는methodCommon()이 호출됩니다.- 결과적으로 두 부모 중에 어떤 한 부모의
methodCommon()을 선택하는 것이 아니라 그냥 인터페이스들을 구현한Child에 있는methodCommon()이 사용됩니다.- 이런 이유로 인터페이스는 다이아몬드 문제가 발생하지 않습니다.
- 따라서 인터페이스의 경우 다중 구현을 허용합니다.
- 이런 이유로 인터페이스는 다이아몬드 문제가 발생하지 않습니다.
- 결과적으로 두 부모 중에 어떤 한 부모의
예제를 코드로 작성해봅시다.
package poly.diamond;
public class Child implements InterfaceA, InterfaceB {
@Override
public void methodA() {
System.out.println("Child.methodA");
}
@Override
public void methodB() {
System.out.println("Child.methodB");
}
@Override
public void methodCommon() {
System.out.println("Child.methodCommon");
}
}
-
ìmplements InterfaceA, InterfaceB와 같이 다중 구현을 할 수 있습니다.-
implements키워드 위에,로 여러 인터페이스를 구분하면 됩니다.
-
-
methodCommon()의 경우 양쪽 인터페이스에 다 있지만 같은 메서드이므로 구현은 하나만 하면 됩니다.
package poly.diamond;
public class DiamondMain {
public static void main(String[] args) {
InterfaceA a = new Child();
a.methodA();
a.methodCommon();
InterfaceB b = new Child();
b.methodB();
b.methodCommon();
}
}
실행 결과
Child.methodA
Child.methodCommon
Child.methodB
Child.methodCommon

-
a.methodCommon()을 호출하면 먼저x001Child인스턴스를 찾는다. - 변수
a가InterfaceA타입이므로 해당 타입에서methodCommon()을 찾습니다. -
methodCommon()은 하위 타입인Child에서 오버라이딩 되어 있습니다. 따라서Child의methodCommon()이 호출됩니다.

-
b.methodCommon()을 호출하면 먼저x001Child인스턴스를 찾습니다. - 변수
b가InterfaceB타입으로 해당 타입에서methodCommon()을 찾습니다. -
methodCommon()은 하위 타입인Child에서 오버라이팅 되어 있습니다. 따라서Child의methodCommon()이 호출됩니다.