
자바 다형성을 학습하던 중, 참조 타입, 호출자 타입, 인스턴스 타입 등의 개념이 서로 헷갈려 제대로 이해하지 못하는 경험이 있을 것입니다. 특히, 다형성이 어떻게 작동하는지 이해하기 위해서는 이러한 타입의 관계를 명확히 구분하는 것이 중요합니다. 이번 글에서는 이 세 가지 타입의 차이점과 이를 어떻게 활용할 수 있는지에 대해 자세히 살펴보겠습니다.
참조 타입은 변수로 선언할 때 사용한 타입을 의미합니다. 이는 참조 변수가 접근할 수 있는 필드와 메서드가 무엇인지 결정합니다. 하지만 실제로 어떤 메서드가 실행될지는 인스턴스 타입(실제 객체의 타입)에 따라 결정됩니다.
Parent parent1 = new Child();
parent1의 참조 타입은 Parent이지만, 실제로 parent1이 참조하는 객체는 Child 클래스의 인스턴스라는 것입니다.
호출자 타입은 메서드를 호출한 변수의 타입을 의미합니다. 메서드를 어떤 참조 변수로 호출하느냐에 따라 호출자 타입이 결정되며, 이를 통해 호출할 수 있는 메서드가 결정됩니다. 즉, 참조 변수의 타입에 따라 호출할 수 있는 메서드가 제한됩니다.
class Parent {
void show() {
System.out.println("Parent의 show()");
}
}
class Child extends Parent {
void show() {
System.out.println("Child의 show()");
}
}
public class Main {
public static void main(String[] args) {
Parent parent1 = new Child(); // 참조 타입: Parent, 인스턴스 타입: Child
parent1.show(); // 호출자 타입: Parent, 실행되는 메서드는 Child의 show()
}
}
parent1.show()를 호출할 때, 호출자 타입은 Parent지만, 실제로 실행되는 메서드는 Child의 show() 메서드입니다. 이는 메서드 오버라이딩 때문에 발생한 다형성입니다. 즉, 호출자 타입은 Parent이지만 실제로 실행되는 메서드는 인스턴스 타입인 Child의 메서드입니다.
인스턴스 타입은 실제로 생성된 객체의 타입을 의미합니다. new 키워드를 사용해 생성된 객체의 클래스 타입이 바로 인스턴스 타입입니다. 중요한 점은 참조 변수의 타입과 인스턴스 타입은 다를 수 있다는 것입니다. 이를 업캐스팅(Upcasting)이라고 하며, 업캐스팅을 통해 부모 클래스 타입의 변수로 자식 클래스 객체를 참조할 수 있습니다.
Parent parent1 = new Child();
다형성은 메서드 오버라이딩을 통해 실제 객체의 타입에 맞는 메서드가 실행되도록 하는 중요한 개념입니다. 이를 이해하기 위해서는 참조 타입, 호출자 타입, 인스턴스 타입의 차이를 구분하는 것이 필수적입니다. 참조 타입은 변수 선언 시 사용한 타입이고, 호출자 타입은 메서드를 호출한 변수의 타입, 인스턴스 타입은 실제 객체의 타입을 의미합니다. 이들 간의 관계를 명확히 이해하면, 다형성의 작동 원리와 메서드가 어떻게 실행되는지 더욱 잘 파악할 수 있습니다.