[Java] 다형성(Polymorphism)

u_yonu·2026년 2월 13일

Java

목록 보기
15/18
post-thumbnail

다형성(Polymorphism)

  • 하나의 객체를 여러 타입의 참조 변수로 다룰 수 있는 성질

  • 즉, 서로 다른 여러 객체를 공통된 타입(상위 클래스/인터페이스) 으로 묶어 동일한 방식으로 처리할 수 있음

  • 상속 관계에서는 부모(조상) 타입 참조 변수로 자식(자손) 객체를 참조할 수 있음

  • 참조 타입이 바뀌어도 실제 객체는 그대로이며, 실행되는 동작(메서드)은 실제 객체 기준으로 결정(동적 바인딩)

    참조 타입 = “무엇으로 보느냐”
    실제 객체 = “진짜 누구냐”
    실행 결과는 진짜 누구냐(실제 객체) 를 따른다.

예시)

Animal a = new Dog();   // Dog 객체를 Animal 타입으로 참조
a.sound();              // 호출은 Dog의 sound()가 실행됨

다형성의 장점

  • 유연성
    상위 클래스 또는 인터페이스 타입 하나로 다양한 구현 객체를 처리할 수 있어, 객체를 쉽게 교체할 수 있다.

  • 재사용성
    공통 로직은 상위 클래스(또는 공통 인터페이스 기반의 공통 처리 코드)에 모으고, 각 클래스는 필요한 부분만 구현해 중복을 줄일 수 있다.

  • 확장성
    새로운 클래스(새 구현체)를 추가해도, 기존 코드는 상위 타입(인터페이스)에만 의존하므로 클라이언트 코드 변경 없이 확장이 가능하다.

  • 유지보수성
    변경이 생겼을 때 영향 범위를 줄일 수 있다.
    구현이 바뀌어도 인터페이스(규격)는 유지하면 되고, 필요하면 구현체만 수정/교체하면 되므로 수정 범위가 작아진다.

다형성의 특징

  • 상속 관계에 있을 때 조상 클래스 타입으로 자손 클래스 객체 참조 가능
참조 타입 변수인스턴스 생성O / X이유
Payment pnew CardPay()OCardPayPayment를 구현 → 상위 타입으로 참조 가능(업캐스팅)
Payment pnew KakaoPay()OKakaoPayPayment를 구현 → 상위 타입으로 참조 가능(업캐스팅)
CardPay cnew CardPay()O같은 타입 객체 생성
CardPay cnew KakaoPay()X서로 다른 구현체(형제 관계) → 상속/구현 관계가 없어 참조 불가
Object onew CardPay()O모든 클래스는 Object를 상속 → Object로 참조 가능

JVM 메모리(힙 영역)

실제 인터페이스 기반으로 객체를 생성할 때, JVM 메모리(힙 영역)에서 실제로 일아나는 일은 다음과 같다.

1) new KakaoPay()는 힙에 객체 1개를 만듬

new KakaoPay()

실행되면 Heap에 KakaoPay 인스턴스(객체) 1개가 생성된다.
이 표현식의 결과는 “객체 자체”가 아니라, 힙에 있는 객체를 가리키는 참조값(주소) 이다.
즉, 힙에는 KakaoPay 객체가 생기고, 그 주소를 다른 변수가 들고 있게 된다.

2) 아래 세 줄은 힙 객체 3개를 만듬

object obj = new KakaoPay() ;
Payment p = new KakaoPay() ;
Kakaopay kp = new KakaoPay() ;
  • 위 코드는 new가 3번이므로, 힙에 KakaoPay 객체가 3개 생김
  • 각각의 참조 변수(obj, p, kp)는 서로 다른 객체의 주소를 들고 있음

3) 같은 힙 객체 1개를 여러 타입으로 참조하려면 아래와 같음

KakaoPay real = new KakaoPay(); // Heap: 객체 1개

Object  obj = real;            // Stack: obj는 그 주소를 들고 있음
Payment p   = real;            // Stack: p도 같은 주소
KakaoPay kp = real;            // Stack: kp도 같은 주소
  • Heap에는 객체 1개
  • Stack에는 참조 변수 3개가 생기고,
  • 세 변수는 전부 같은 주소(같은 객체) 를 가리킴

4) 참조 타입이 다르면 '보이는 범위'가 달라짐
(1) Object obj

obj.toString(); // O (Object에 있는 메서드)
  • Object 타입이라 Object가 가진 기능만 보임

(2) Payment p

p.pay(1000);   // O (Payment 규격에 있는 메서드)
  • Payment 타입이라 인터페이스에 선언된 메서드만 보임

(3) KakaoPay kp

kp.pay(1000);      // O
kp.kakaoOnly();    // O (KakaoPay 전용 메서드가 있다면)
  • 구체 타입이라 KakaoPay 전용 기능까지 보임

참조변수의 형 변환

예시)
KakaoPay implements Payment
CardPay implements Payment
그리고 모든 클래스는 Object를 상속

Object
↳ KakaoPay (그리고 Payment를 구현)
↳ CardPay (그리고 Payment를 구현)

  • 인터페이스는 상속이 아니라 구현이지만, 캐스팅 방향(위로/아래로) 개념은 똑같이 적용

(1) 업캐스팅 : 자손 -> 조상

  • 묵시적 형 변환 가능
  • 안전함 (무조건 성립)
KakaoPay kp = new KakaoPay();
Payment p = kp;        // 업캐스팅 (생략 가능)
Object obj = kp;       // 업캐스팅 (생략 가능)

p.pay(10000);      // O (Payment에 있음)
p.kakaoOnly();     // X (Payment에는 없음)

(2) 다운캐스팅 : 조상 -> 자손

  • 명시적 형 변환 필요: (KakaoPay) p

  • 항상 가능한 게 아님 (진짜 객체가 KakaoPay일 때만 가능)

잘못된 예시 1)

Payment p = new CardPay();   // 실제 객체는 CardPay
KakaoPay kp = (KakaoPay) p;  // X (런타임 ClassCastException)

p의 “타입”은 Payment지만 p가 가리키는 “실제 객체”가 CardPay라서 KakaoPay로 못바꿈

instanceof 연산자

instanceof는 '참조 변수가 가리키는 실제 객체가 어떤 타입인지' 확인할 때 쓴다.
-> 결과를 boolean으로 반환
-> true가 반환이 되면 해당 타입으로 형 변환 가능

Payment p = new KakaoPay();

p instanceof Payment   // true
p instanceof KakaoPay  // true
p instanceof CardPay   // false
p instanceof Object    // true

사용 이유 : 다운캐스팅은 위험할 수 있어서

Payment p = new CardPay();

// 아래는 위험: 실제 객체가 CardPay인데 KakaoPay로 바꾸려 하면 런타임 에러
KakaoPay kp = (KakaoPay) p; // ClassCastException

사용 예시

Payment p = new KakaoPay();

if (p instanceof KakaoPay) {
    KakaoPay kp = (KakaoPay) p;
    kp.kakaoOnly();   // KakaoPay 전용 기능 사용
}

cf) Java 16+ 패턴 매칭

  • instanceof KakaoPay가 true면, kp 변수가 자동으로 KakaoPay 타입으로 선언된 것처럼 사용 가능
Payment p = new KakaoPay();

if (p instanceof KakaoPay kp) {
    kp.kakaoOnly();
}

참조 변수와 인스턴스 멤버의 관계

  • 상속관계에서 멤버변수가 중복이 되면 참조 변수 타입에 따라 연결이 달라짐
  • 메서드가 중복될 때(오버라이딩), 참조 변수의 타입에 상관없이 항상 실제 인스턴스의 자식 클래스 메서드가 호출 -> 동적 바인딩
  • static 메서드는 참조변수 타입의 영향을 받기 때문에 이를 방지하고자 클래스 이름으로 메서드 호출(권장)

객체 지향 프로그래밍에서 특성 중 하나인 '다형성'에 대한 설명

profile
비전공자의 개발도전기

0개의 댓글