[인프런 Java] 인터페이스 - 다중 구현

코드 속의 "진돌"·2024년 3월 22일
0
post-thumbnail

✅ 인터페이스 - 다중 구현


📚 자바가 다중 상속을 지원하지 않는 이유

자바는 다중 상속을 지원하지 않는다. 그래서 extends 대상은 하나만 선택할 수 있다. 부모를 하나만 선택할 수 있다는 뜻이다. 물론 부모가 또 부모를 가지는 것은 괜찮다.


✓ 다중 상속 그림

만약 비행기와 자동차를 상속 받아서 하늘을 나는 자동차를 만든다고 가정해보자. 만약 그림과 같이 다중 상속을 사용하게 되면 AirplaneCar 입장에서 move()를 호출할 때 어떤 부모의 move()를 사용해야 할 지 애매한 문제가 발생한다. 이것을 다이아몬드 문제라 한다. 그리고 다중 상속을 사용하면 클래스 계층 구조가 매우 복잡해질 수 있다. 이런 문제점 때문에 자바는 클래스의 다중 상속을 허용하지 않는다. 대신에 인터페이스의 다중 구현을 허용하여 이러한 문제를 피한다.

클래스는 앞서 설명한 이유로 다중 상속이 안되는데, 인터페이스의 다중 구현은 허용한 이유는 뭘까?
인터페이스는 모두 추상 메서드로 이루어져 있기 때문이다.


✓ 인터페이스 다중 구현 그림

InterfaceA, InterfaceB는 둘 다 같은 methodCommon()을 가지고 있다. 그리고 Child는 두 인터페이스를 구현했다. 상속 관계의 경우 두 부모 중에 어떤 한 부모가 methodCommon()을 사용해야 할 지 결정해야 하는 다이아몬드 문제가 발생한다.

하지만 인터페이스 자신은 구현을 가지지 않는다. 대신에 인터페이스를 구현하는 곳에서 해당 기능을 모두 구현해야 한다. 여기서 InterfaceA, InterfaceB는 같은 이름의 methodCommon()을 제공하지만 이것의 기능은 Child가 구현한다. 그리고 오버라이딩에 의해 어차피 Child에 있는 methodCommon()이 호출된다. 결과적으로 두 부모 중에 어떤 한 부모의 methodCommon()을 선택하는 것이 아니라 그냥 인터페이스들을 구현한 Child에 있는 methodCommon()이 사용된다. 이런 이유로 인터페이스는 다이아몬드 문제가 발생하지 않는다. 따라서 인터페이스의 경우 다중 구현을 허용한다.



✏️ InterfaceA

package poly.diamond;

public interface InterfaceA {
  void methodA();
  void methodCommon();
}



✏️ InterfaceB

package poly.diamond;

public interface InterfaceB {
  void methodB();
  void methodCommon();
}



✏️ Child

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");
  }
}
  • implements InterfaceA, InterfaceB와 같이 다중 구현을 할 수 있다. implements 키워드 뒤에 ,로 여러 인터페이스를 구분하면 된다.
  • methodCommon()의 경우 양쪽 인터페이스에 다 있지만 같은 메서드이므로 구현은 하나만 하면 된다.



✏️ DiamondMain

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



🖥️ 실행 결과



⚙️ 코드 설명

  1. a.methodCommon()을 호출하면 먼저 x001 Child 인스턴스를 찾는다.
  2. 변수 aInterfaceA 타입이므로 해당 타입에서 methodCommon()을 찾는다.
  3. methodCommon()은 하위 타입인 Child에서 오버라이딩 되어 있다. 따라서 ChildmethodCommon()이 호출된다.

  1. b.methodCommon()을 호출하면 먼저 x001 Child 인스턴스를 찾는다.
  2. 변수 bInterfaceB 타입이므로 해당 타입에서 methodCommon()을 찾는다.
  3. methodCommon()은 하위 타입인 Child에서 오버라이딩 되어 있다. 따라서 ChildmethodCommon()이 호출된다.

출처 : 김영한의 실전 자바 - 기본편
https://www.inflearn.com/course/김영한의-실전-자바-기본편/dashboard

profile
매일 성장하는 주니어 개발자의 기록📝

0개의 댓글