객체지향 프로그래밍의 3대 특징은 캡슐화, 상속, 다형성이다. 그중 다형성은 흔히 "객체지향의 꽃"이라 불린다. 이유는, 다형성을 이해하고 활용할 줄 알면 코드의 유연성, 확장성, 재사용성이 극대화되기 때문이다. 이번 글에서는 다형성의 핵심인 다형적 참조와 메서드 오버라이딩을 중심으로 정리해보겠다.
다형성의 시작
- 다형성(Polymorphism) = "여러 형태"
- 하나의 객체가 여러 타입으로 참조될 수 있는 능력이다.
- 즉, 같은 객체라도 부모 타입, 자식 타입 등 다양한 변수 타입으로 참조 가능하다.
다형적 참조 (Polymorphic Reference)
class Parent {
public void parentMethod() {
System.out.println("Parent.parentMethod");
}
}
class Child extends Parent {
public void childMethod() {
System.out.println("Child.childMethod");
}
}
Parent p1 = new Parent(); // Parent → Parent
Child c1 = new Child(); // Child → Child
Parent p2 = new Child(); // Parent → Child (다형적 참조)
- Parent → Parent: 부모 변수로 부모 인스턴스 참조
- Child → Child: 자식 변수로 자식 인스턴스 참조
- Parent → Child: 부모 변수로 자식 인스턴스 참조 가능
- 부모는 자식을 품을 수 있다. 하지만 자식은 부모를 품을 수 없다.
캐스팅 (Casting)
- 업캐스팅 (Upcasting): 자식 → 부모 (자동 변환 가능함)
- 다운캐스팅 (Downcasting): 부모 → 자식 (명시적 변환 필요함)
Parent p = new Child(); // 업캐스팅 (자동)
Child c = (Child) p; // 다운캐스팅 (명시적)
- 업캐스팅은 안전하지만, 다운캐스팅은 위험하다.
- 잘못된 다운캐스팅 시 ClassCastException이 발생한다.
일시적 다운캐스팅
다운캐스팅을 변수에 담지 않고 즉시 호출할 수도 있다.
((Child) p).childMethod();
- p를 순간적으로 Child로 바꿔서 메서드를 호출한다.
instanceof 연산자
다운캐스팅 전에 안전하게 타입을 확인하려면 instanceof를 사용한다.
if (p instanceof Child) {
Child c = (Child) p; c.childMethod();
}
- true → 해당 타입으로 변환 가능함을 의미한다.
- false → 변환이 불가능함을 의미한다. (ClassCastException 방지)
- 자바 16부터는 Pattern Matching 문법으로 더 간단하게 사용할 수 있다. (아래 코드 참고)
if (p instanceof Child c) { c.childMethod(); }
다형성과 메서드 오버라이딩
다형성의 진짜 힘은 오버라이딩과 결합할 때 나타난다.
class Parent {
public String value = "parent";
public void method() {
System.out.println("Parent.method");
}
}
class Child extends Parent {
public String value = "child";
@Override
public void method() {
System.out.println("Child.method");
}
}
Parent poly = new Child();
System.out.println(poly.value); // parent (변수는 오버라이딩 X)
poly.method(); // Child.method (메서드는 오버라이딩 O)
- 변수는 오버라이딩되지 않는다 → 타입 기준으로 접근한다
- 메서드는 오버라이딩된다 → 실제 인스턴스를 기준으로 실행된다
- 즉, 메서드 오버라이딩은 항상 우선권을 가진다.
정리하자면...
- 다형성 = 하나의 객체를 여러 타입으로 참조할 수 있는 능력
- 부모는 자식을 참조할 수 있지만, 자식은 부모를 참조할 수 없다
- 업캐스팅은 안전, 다운캐스팅은 위험 → 반드시 instanceof 확인하기
- 변수는 타입 기준, 메서드는 인스턴스 기준으로 실행 (오버라이딩)
- 다형성과 오버라이딩을 함께 쓰면 코드의 유연성과 확장성이 폭발적으로 증가한다
다형성 + 오버라이딩은 객체지향의 꽃이다!
'java' 카테고리의 다른 글
| Java 상속과 다이아몬드 문제(Diamond Problem) (0) | 2025.09.16 |
|---|---|
| Java 다형성(Polymorphism) 심화: 추상 클래스와 인터페이스 (0) | 2025.09.16 |
| Java 상속(Inheritance) 정리 (0) | 2025.09.15 |
| Java final 키워드 정리 (2) | 2025.09.15 |
| Java 메모리 구조와 static 정리 (0) | 2025.09.15 |