Java 다형성 - 인터페이스 다중 구현

​자바 extends 상속에서는 부모의 부모로 두는 경우 문제가 없으나, 자식 클래스에서 여러 명의 부모를 지정할 수 없었다.

extends 다중 구현

extends 상속을 사용하는 경우를 살펴 보도록한다.
예제는 수상해서 이동하는 차 입장에서 move() 호출한 경우 어떤 부모의 move() 사용해야하는지 애매한 다이아몬드 문제가 발생한다.
다중 상속은 클래스 계층 구조가 복잡해지고 자바의 상속은 다중 상속을 허용치 않는다.
interface 는 이러한 메소드가 추상 메소드인 점과 자식에서 구현한다는 것을 이용해 다중 상속을 허용하여 다이아몬드 문제를 피할 수 있었다.

interface 다중 구현

InterfaceA, InterfaceB 공통된 메소드 press() 를 갖고 있다.
상속을 받은 InterfaceC 에서 해당 press() 구현하고, 두 부모 중 press() 사용해야 하는 다이아몬드 결정 문제가 있다.
하지만 해당 부모의 인터페이스는 press() 이름만 제공할 뿐, InterfaceC 인터페이스에서 구현되어 이 문제를 회피할 수 있었다.
부모의 press() 가 아닌 자식의 press() 사용함으로써 다이아몬드 결정 문제는 발생되지 않았다.

예제 코드

InterfaceA.java

package diamond;

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

InterfaceB.java

package diamond;

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

InterfaceC.java

package diamond;

public class InterfaceC implements InterfaceA, InterfaceB{

    @Override
    public void methodA() {
        System.out.println("methodA");
    }

    @Override
    public void methodB() {
        System.out.println("methodB");
    }

    @Override
    public void press(){
        System.out.println("I'm pressed!");
    }
}

다중 상속은 implements 키워 뒤에 인터페이스명을 (,) 컴마로 구분하여 작성한다.
press() 메소드는 부모 모두 갖고 있지만 구현은 자식에서 이루어진다.

InterfaceMain

package diamond;

public class InterfaceMain {
    public static void main(String[] args) {
        InterfaceA c = new InterfaceC();
        c.methodA();
        c.press();

        InterfaceB b = new InterfaceC();
        b.methodB();
        b.press();
    }
}

실행결과

methodA
I'm pressed!
methodB
I'm pressed!
methodA
methodB
I'm pressed!

코드 InterfaceA a = new InterfaceC() 살펴보기

InterfaceA a = new InterfaceC();
a.methodA();
a.press();
  • InterfaceA 변수에게 InterfaceC 인스턴스를 생성하였다.
  • methodA(), press() 메소드는 인스턴스 내부로 InterfaceA 가리켜서 메소드를 찾고, 오버라이딩된 자식이 있으니 그 곳에서 기능을 호출한다.

그림으로 살펴보도록 한다.

코드 InterfaceB b = new InterfaceC() 살펴보기

InterfaceB b = new InterfaceC();
b.methodA();
b.press();
  • InterfaceB 변수에게 InterfaceC 인스턴스를 생성하였다.
  • methodB(), press() 메소드는 인스턴스 내부로 InterfaceB 가리켜서 메소드를 찾고, 오버라이딩된 자식이 있으니 그 곳에서 기능을 호출한다.