본문 바로가기
기초 및 언어/▶ Java&JSP

21. 다형성, 업캐스팅, 다운캐스팅

by 류딩이 2025. 8. 20.

1. 다형성(Polymorphism)

 

다형성(Polymorphism) 이란?

하나의 참조변수로 여러 타입의 객체를 참조할 수 있는 것

 

즉, 부모 클래스 타입의 참조변수로 자식 객체를 다룰 수 있는 것을 말합니다.

class Animal { 
    public void move() {
        System.out.println("동물이 움직인다.");
    }
}

class Person3 extends Animal {
    @Override
    public void move() {
        System.out.println("사람이 걷는다.");
    }
}

class Bird extends Animal {
    @Override
    public void move() {
        System.out.println("새가 날아간다.");
    }
}

public class Ex07_다형성 {
    public static void main(String[] args) {
        Animal a = new Animal();
        a.move(); // Animal의 move 실행

        Person3 p = new Person3();
        p.move(); // Person3의 move 실행

        Bird b = new Bird();
        b.move(); // Bird의 move 실행

        System.out.println("====== 다형성 ======");

        // 업캐스팅 (자식을 부모 타입으로 참조)
        Animal p2 = new Person3(); // Person3 객체를 Animal 타입으로 참조
        p2.move(); // 실제 객체(Person3)의 move 실행

        Animal b2 = new Bird(); // Bird 객체를 Animal 타입으로 참조
        b2.move(); // 실제 객체(Bird)의 move 실행
    }
}

 

2. 업캐스팅(Upcasting)

  • 자식 객체를 부모 타입 변수에 저장하는 것
  • 형변환 연산자를 쓰지 않아도 자동으로 변환됩니다.
double i = 3;  // 업캐스팅

Animal p2 = new Person3(); // 업캐스팅
Animal b2 = new Bird();    // 업캐스팅

 

업캐스팅 후 move()를 호출하면, 부모의 것이 아니라 자식 클래스에서 오버라이딩한 메서드가 실행됩니다.

  • p2.move() → "사람이 걷는다."
  • b2.move() → "새가 날아간다."

 

        Animal p2 = new Person3(); // Person3 객체를 Animal 타입으로 참조
        p2.move(); // 실제 객체(Person3)의 move 실행

        Animal b2 = new Bird(); // Bird 객체를 Animal 타입으로 참조
        b2.move(); // 실제 객체(Bird)의 move 실행

 

다형성에서의 실행 과정 (업캐스팅 후 메서드 호출)

1️⃣ Animal p2 = new Person3();

  • p2.move() 실행 흐름
    1. 참조변수 p2는 Animal 타입이므로, 컴파일러는 Animal 클래스에 move()가 존재하는지 확인합니다.
    2. Animal에 move()가 있으므로 호출 가능 ✅
    3. 실행 시점에 p2가 실제로 가리키는 객체는 Person3 → 따라서 Person3의 move() 실행

👉 결과: "사람이 걷는다."


2️⃣ Animal b2 = new Bird();

  • b2.move() 실행 흐름
    1. 참조변수 b2는 Animal 타입이므로, 컴파일러는 Animal 클래스에 move()가 존재하는지 확인합니다.
    2. Animal에 move()가 있으므로 호출 가능 ✅
    3. 실행 시점에 b2가 실제로 가리키는 객체는 Bird → 따라서 Bird의 move() 실행

👉 결과: "새가 날아간다."

 

👉 그러니까,

  • p2 => Person3의 move 출력
  • b2 => Bird의 move 출력

둘 다 Animal(부모)이 move()를 가지고 있기 때문에 자식에서 오버라이딩된 메서드가 실행된 거예요.

 

🔎 객체 생성 vs 업캐스팅

 

1.객체 생성(new)

new FullTime("F01", "인간3", 100, 400);

 

👉 이건 그냥 FullTime 객체를 힙에 생성하는 동작
아직 "캐스팅"은 일어나지 않음.

 

2. 업캐스팅

Employee e = new FullTime("F01", "인간3", 100, 400);

 

👉 여기서 new FullTime(...)으로 만든 FullTime 객체Employee 타입 참조 변수 e에 담으면서 업캐스팅이 발생

 

 

📌 정리

  • new → 객체 생성 (자식 타입 객체가 실제로 메모리에 만들어짐)
  • = 대입할 때, 부모 타입 변수에 자식 객체를 담으면 업캐스팅
FullTime f = new FullTime(...);   // 업캐스팅 아님 (자식 → 자식)
Employee e = new FullTime(...);   // ✅ 업캐스팅 (자식 → 부모)
  • 업캐스팅 후 메서드 호출 시, 부모 클래스에 메서드가 존재하는지 먼저 확인해야 한다.
  • 실행할 때는 실제 객체 타입(new Person3(), new Bird())의 메서드가 실행된다.
  • 이것이 다형성(Polymorphism) + 동적 바인딩(Dynamic Binding) 의 원리이다.

 

 

2. 다운캐스팅(Downcasting)

 

  • 부모 → 자식 타입으로 변환 (강제 변환 필요)
  • 반드시 instanceof 로 타입 체크 후 사용해야 안전
  • 업캐스팅된 객체만 다운캐스팅 가능
class Car {
    String color = "white"; // 인스턴스 변수 초기값
    int door = 4;
    
    void drive() {
        System.out.println("drive");
    }
    void stop() {
        System.out.println("stop!");
    }
}

class FireEngine extends Car { // Car를 상속받음
    int door = 6;
    int wheel = 10;

    @Override
    public void drive() {
        System.out.println("FEdrive"); // 오버라이딩
    }
    void water() {
        System.out.println("water 뿌우");
    }
}

public class Ex08_다형성 {
    public static void main(String[] args) {
        Car c;                  // 부모 타입 참조 변수
        FireEngine fe = new FireEngine();
        FireEngine fe2;         // 아직 객체 할당 전

        // ✅ 업캐스팅 : 자식을 부모 타입으로 변환
        c = fe; // c = (Car)fe; 와 동일 (자동 변환)
        
        System.out.println("===== c. =====");
        System.out.println(c.door);  // 4 (Car의 멤버변수 참조)
        // System.out.println(c.wheel); // ❌ 에러! Car에는 wheel이 없음

        System.out.println("===== fe. =====");
        System.out.println(fe.door);   // 6 (자식 클래스 FireEngine 멤버변수 참조)
        System.out.println(fe.wheel);  // 10
        System.out.println(fe.color);  // white (부모로부터 상속)

        // ✅ 메서드 호출 시 다형성 적용
        c.drive();  // FireEngine의 drive() 실행됨 (오버라이딩 때문)

        // ❌ FireEngine fe2 = new Car();  // 오류: 부모 객체는 자식에 대입 불가

        // ✅ 다운캐스팅 확인
        if(c instanceof FireEngine) {
            System.out.println("다운 캐스팅 가능");
        } else {
            System.out.println("다운 캐스팅 불가능");
        }

        // ✅ 다운캐스팅 : 부모 → 자식
        fe2 = (FireEngine)c;
        fe2.water();
        fe2.drive();
    }
}

 

 

if(c instanceof FireEngine) {
    FireEngine fe2 = (FireEngine)c; // 다운캐스팅
    fe2.water();
}

 

 

 

 

 

'기초 및 언어 > ▶ Java&JSP' 카테고리의 다른 글

23. 추상클래스, 인터페이스  (5) 2025.08.20
22. import  (0) 2025.08.20
20. 제어자, 접근제어지시자(Access Modifier)와 기타제어자  (0) 2025.08.19
19. 포함  (0) 2025.08.19
18. 상속  (0) 2025.08.19