인터페이스는 클래스와 마찬가지로 다른 인터페이스에서 상속할 수 있습니다.
클래스를 구현하지 않는 인터페이스도 다른 인터페이스를 상속합니다.
인터페이스는 extend 키워드를 통해 다른 인터페이스도 상속할 수 있으며 중요한 점은 클래스와 달리 인터페이스는 다중 상속을 허용합니다.
이전에는 부모/자식 클래스로 통칭했지만 각 인터페이스를 부모/자식 인터페이스라고 합니다.
public interface 하위인터페이스 extends 상위인터페이스1, 상위인터페이스2... {
//...
}
상속이 발생하므로 당연히 다형성의 품질이 있습니다.
예를 들어, 위의 “하위 인터페이스” 예제를 구현하는 “구현 클래스”가 있다고 가정합니다.
이 ‘구현 클래스’는 ‘하위 인터페이스’, ‘상위 인터페이스 1’, ‘상위 인터페이스 2’ 외에… 모든 추상 메서드를 재정의하고 구현해야 합니다.
이 경우 “구현 클래스”의 인스턴스를 생성하면 상속에서 수정되지 않은 다형성의 특성을 적용하여 유형 변환이 가능합니다.
이것이 무엇을 의미하는지 약간 혼란스럽다면 아래 코드를 살펴보십시오.
하위인터페이스 변수 = new 구현클래스();
상위인터페이스1 변수 = new 구현클래스();
상위인터페이스2 변수 = new 구현클래스();
‘구현 클래스’ 인스턴스는 ‘상위 인터페이스 1’과 ‘상위 인터페이스 2’ 모두에 가정된 추상 메서드를 구현하므로 상위 타입 인터페이스를 이용한 타입 변환이 가능하다.
클래스 상속에 적용되는 동일한 개념이 인터페이스에도 적용됩니다.
물론 ‘구현 클래스’의 인스턴스를 ‘하위 인터페이스’로 캐스팅하면 모든 추상 메서드를 사용할 수 있습니다.
단, “상위인터페이스 1” 또는 “상위인터페이스 2″로 타입을 변환하면, 하위 인터페이스에 선언된 메서드만 사용할 수 없겠죠?
위의 설명을 예제와 함께 살펴보겠습니다.
세 가지 인터페이스 인터페이스X / 인터페이스Y / 인터페이스Z존재한다고 가정하면 여기서 하위 인터페이스는 InterfaceZ가 되고 이 인터페이스는 InterfaceX와 InterfaceY가 상속한 구조를 가집니다.
참고로 InterfaceX와 InterfaceY는 같은 수준의 독립적인 인터페이스입니다.
InterfaceZ는 다중 상속을 병렬로 수행합니다.
모든 인터페이스 방법X / 방법Y / 방법Z가지다
public interface InterfaceX {
public void methodX();
}
public interface InterfaceY {
public void methodY();
}
public interface InterfaceZ extends InterfaceX, InterfaceY {
public void methodZ();
}
public class ImplementationZ implements InterfaceZ {
public void methodX() {
System.out.println("methodX 실행");
}
public void methodY() {
System.out.println("methodY 실행");
}
public void methodZ() {
System.out.println("methodZ 실행");
}
}
public class ExampleMain {
public static void main(String() args) {
InterfaceX ix = new ImplementationZ();
ix.methodX();
System.out.println();
InterfaceY iy = new ImplementationZ();
iy.methodY();
System.out.println();
InterfaceZ iz = new ImplementationZ();
iz.methodX();
iz.methodY();
iz.methodZ();
}
}
/* 출력
methodX 실행
methodY 실행
methodX 실행
methodY 실행
methodZ 실행
*/