Java에서 상위 클래스 또는 인터페이스 타입의 참조 변수에 하위 클래스 객체를 할당하면, 해당 참조를 통해 접근할 수 있는 멤버는 참조 변수의 타입이 결정합니다. 즉, 인터페이스 타입의 참조 변수로는 인터페이스에 선언된 멤버만 호출할 수 있으며, 하위 클래스에만 존재하는 멤버에 접근하려고 하면 컴파일 시점에 오류가 발생합니다.
컴파일 오류가 발생하는 예제
interface Sample {
void demoMethod1();
}
public class InterfaceExample implements Sample {
public void display() {
System.out.println("This is a method of the sub class");
}
public void demoMethod1() {
System.out.println("This is demo method-1");
}
public static void main(String args[]) {
Sample obj = new InterfaceExample();
obj.demoMethod1();
obj.display();
}
}
위 코드에서 obj는 Sample 인터페이스 타입으로 선언되었기 때문에, Sample에 정의되어 있지 않은 display() 메서드를 호출하는 순간 다음과 같은 컴파일 오류가 발생합니다.
출력 결과
InterfaceExample.java:14: error: cannot find symbol
obj.display();
^
symbol: method display()
location: variable obj of type Sample
1 error
캐스팅을 통한 해결 방법
상위 클래스(또는 인터페이스) 타입의 참조 변수로 하위 클래스의 멤버에 접근해야 하는 경우에는, 캐스팅 연산자를 사용해 참조 변수를 하위 클래스 타입으로 명시적으로 형 변환(다운캐스팅)해 주어야 합니다.
예제
interface Sample {
void demoMethod1();
}
public class InterfaceExample implements Sample {
public void display() {
System.out.println("This is a method of the sub class");
}
public void demoMethod1() {
System.out.println("This is demo method-1");
}
public static void main(String args[]) {
Sample obj = new InterfaceExample();
obj.demoMethod1();
((InterfaceExample) obj).display();
}
}
((InterfaceExample) obj)와 같이 참조 변수를 실제 객체의 타입으로 캐스팅하면, 하위 클래스의 모든 멤버에 정상적으로 접근할 수 있습니다.
출력 결과
This is demo method-1 This is a method of the sub class
참고: 다운캐스팅 시 실제 객체가 해당 타입이 아니라면 실행 시점에 ClassCastException이 발생할 수 있습니다. 따라서 안전한 코드를 작성하려면 캐스팅 전에 instanceof 연산자로 객체의 실제 타입을 확인하는 것이 좋습니다.