놀랍게도... 인터페이스는 인터페이스 끼리 상속이 가능하다. 또한 상속과 다르게 다중 상속도 가능하다.
하위 인터페이스를 구현하는 클래스는 하위 인터페이스의 메소드 뿐만 아니라 상위 인터페이스의 모든 추상 메소드에 대한 실체 메소드를 가지고 있어야 한다.
때문에 구현 클래스로부터 객체를 생성하고 나서 하위 및 상위 인터페이스 타입으로 변환이 가능하다.
하위 인터페이스로 타입 변환이 되면 상, 하위 인터페이스에 선언된 모든 메소드에 접근 가능!
하지만 상위 인터페이스로 타입변환이 된다면 상위 인터페이스에 선언된 메소드만 사용이 가능하다.
public interface InterfaceA {
void methodA();
}
public interface InterfaceB {
void methodB();
}
public interface InterfaceC extends InterfaceA, InterfaceB{ // 인터페이스 특징: 인터페이스가 인터페이스를 상속받을 수도 있다. (extends로 받아야 함)
void methodC();
}
public class InterfaceCImpl implements InterfaceC { // 인터페이스 상속이니까 implements
// InterfaceA와 InterfaceB의 실체 메소드까지 모두 가지고 있어야 한다.
@Override
public void methodA() {
System.out.println("InterfaceCImpl methodA()");
}
@Override
public void methodB() {
System.out.println("InterfaceCImpl methodB()");
}
@Override
public void methodC() {
System.out.println("InterfaceCImpl methodC()");
}
}
public class ExtendsEx {
public static void main(String[] args) {
InterfaceCImpl impl = new InterfaceCImpl();
InterfaceA ia = impl; // 자동 형변환
ia.methodA();
// ia.methodB(); // 에러
// ia.methodC(); // 에러 (이유: InterfaceA는 추상메소드로 methodA밖에 없으니깐)
InterfaceB ib = impl; // 자동 형변환
ib.methodB();
InterfaceC ic = impl; // 자동 형변환
// ★ InterfaceC는 InterfaceA, InterfaceB를 상속을 받았으므로 아래와 같이 호출 가능
ic.methodA(); // InterfaceA와 InterfaceB의 추상메소드를 모두 가져올 수 있다.
ic.methodB();
ic.methodC();
}
}
[출력결과]
InterfaceCImpl methodA()
InterfaceCImpl methodB()
InterfaceCImpl methodA()
InterfaceCImpl methodB()
InterfaceCImpl methodC()
InterfaceA 변수는 methodA만 호출이 가능하다.
InterfaceB 변수는 methodB만 호출이 가능하다.
하지만 InterfaceC변수는 methodA, methodB, methodC 모두 호출이 가능하다!