전의 예제는 클래스의 상속 관계를 통해서 다형성을 설명하고 있는데, 다형성의 세계에서는 인터페이스도 중요한 수단이다. 인터페이스 수업에서는 언급하지 않은 것이 있다. 특정한 인터페이스를 구현하고 있는 클래스가 있을 때 이 클래스의 데이터 타입으로 인터페이스를 지정 할 수 있다. 말이 어렵다면 코드를 통해서 무슨 말인지 알아보자.
package org.opentutorials.javatutorials.polymorphism; interface I{} class C implements I{} public class PolymorphismDemo2 { public static void main(String[] args) { I obj = new C(); } }
위의 코드를 통해서 알 수 있는 것은 클래스 C의 데이터 타입으로 인터페이스 I가 될 수 있다는 점이다. 이것은 다중 상속이 지원되는 인터페이스의 특징과 결합해서 상속과는 다른 양상의 효과를 만들어낸다. 아래 코드를 보자.
package org.opentutorials.javatutorials.polymorphism; interface I2{ public String A(); } interface I3{ public String B(); } class D implements I2, I3{ public String A(){ return "A"; } public String B(){ return "B"; } } public class PolymorphismDemo3 { public static void main(String[] args) { D obj = new D(); I2 objI2 = new D(); I3 objI3 = new D(); obj.A(); obj.B(); objI2.A(); //objI2.B(); //objI3.A(); objI3.B(); } }
주석처리된 메소드 호출은 오류가 발생하는 것들이다. objI2.b()에서 오류가 발생하는 이유는 objI2의 데이터 타입이 인터페이스 I이기 때문이다. 인터페이스 I는 메소드 A만을 정의하고 있고 I를 데이터 타입으로 하는 인스턴스는 마치 메소드 A만을 가지고 있는 것처럼 동작하기 때문이다.
이것은 인터페이스의 매우 중요한 특징 중의 하나를 보여준다. 인스턴스 objI2의 데이터 타입을 I2로 한다는 것은 인스턴스를 외부에서 제어할 수 있는 조작 장치를 인스턴스 I2의 맴버로 제한한다는 의미가 된다. 인스턴스 I2와 I3로 인해서 하나의 클래스가 다양한 형태를 띄게 되는 것이다.