Menu
Coddy logo textTech

업캐스팅과 다운캐스팅

Coddy Java 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 87개 중 30번째.

이전 레슨에서 부모 타입 변수가 자식 객체를 어떻게 보유할 수 있는지 살펴보았습니다: Animal myPet = new Dog(). 이러한 대입을 업캐스팅(upcasting)이라고 하며, Dog는 항상 Animal이므로 이는 자동으로 수행됩니다.

업캐스팅(Upcasting)은 상속 계층 구조를 따라 위로 올라갑니다. 이는 암시적이며 항상 안전합니다:

Dog dog = new Dog();
Animal animal = dog;  // 업캐스팅 - 자동

업캐스팅(upcast)을 하면 부모 클래스에 정의된 메서드에만 접근할 수 있습니다. 객체는 내부적으로 여전히 Dog이지만, 자식 클래스 전용 메서드들은 숨겨지게 됩니다.

다운캐스팅(Downcasting)은 반대 방향으로 진행되며, 부모 참조를 다시 자식 타입으로 변환합니다. 이것은 항상 안전하지는 않기 때문에 명시적 캐스팅이 필요합니다:

Animal animal = new Dog();  // 업캐스팅
Dog dog = (Dog) animal;     // 다운캐스팅 - 명시적 형변환 필요
dog.bark();                 // 이제 Dog 메서드에 접근할 수 있습니다

다운캐스팅은 위험합니다. 만약 객체가 실제로 캐스팅하려는 타입이 아니라면, Java는 런타임에 ClassCastException을 발생시킵니다:

Animal animal = new Cat();
Dog dog = (Dog) animal;  // 컴파일은 되지만 실행 시점에 오류가 발생합니다!

컴파일러는 선언된 타입만 볼 수 있기 때문에 이 오류를 포착할 수 없습니다. 실제 객체 타입은 프로그램이 실행될 때 비로소 알 수 있습니다. 다음 단원에서는 다운캐스팅을 하기 전에 객체의 타입을 안전하게 확인하는 방법을 배울 것입니다.

challenge icon

챌린지

쉬움

업캐스팅(upcasting)과 다운캐스팅(downcasting)이 실제로 어떻게 작동하는지 보여주는 미디어 플레이어 시스템을 구축해 보겠습니다. 미디어 유형의 계층 구조를 만들고 부모 참조와 자식 참조 간의 변환을 연습하게 됩니다.

코드는 다음 네 개의 파일로 구성됩니다:

  • Media.java: 모든 미디어 유형이 공유하는 기본 클래스를 생성합니다. 모든 미디어 항목은 title 필드(String)를 가집니다. 이를 초기화하는 생성자, 게터 메서드 getTitle(), 그리고 Playing: [title]을 출력하는 play() 메서드를 포함하세요.
  • Song.java: Media를 상속받는 클래스를 생성합니다. 노래는 추가로 artist 필드(String)를 가집니다. 부모 초기화를 위해 super를 사용하세요. play()를 오버라이드하여 Playing song: [title] by [artist]를 출력하도록 합니다. Artist: [artist]를 출력하는 showArtist() 메서드를 추가하세요.
  • Podcast.java: Media를 상속받는 또 다른 클래스를 생성합니다. 팟캐스트는 episode 필드(int)를 가집니다. play()를 오버라이드하여 Playing podcast: [title] - Episode [episode]를 출력하도록 합니다. Episode: [episode]를 출력하는 showEpisode() 메서드를 추가하세요.
  • Main.java: 미디어 유형을 사용하여 업캐스팅과 다운캐스팅을 시연합니다. 노래 제목, 아티스트 이름, 팟캐스트 제목, 에피소드 번호의 네 가지 입력을 받게 됩니다.

    먼저, Song을 생성하고 이를 Media 참조로 업캐스팅합니다. 이 참조에서 play()를 호출하여 런타임 다형성이 작동하는 것을 확인하세요.

    다음으로, 해당 Media 참조를 다시 Song으로 다운캐스팅하고 showArtist()를 호출하여 자식 클래스 전용 메서드에 접근합니다.

    그런 다음, Podcast를 생성하고 이를 Media 참조로 업캐스팅합니다. 이 참조에서 play()를 호출하세요.

    마지막으로, 해당 Media 참조를 다시 Podcast로 다운캐스팅하고 showEpisode()를 호출합니다.

네 가지 입력을 받게 됩니다: 노래 제목(String), 아티스트 이름(String), 팟캐스트 제목(String), 에피소드 번호(int).

출력은 네 줄로 표시되어야 합니다. 노래에 대한 두 줄(재생 출력 및 아티스트 정보)과 팟캐스트에 대한 두 줄(재생 출력 및 에피소드 정보)입니다. 업캐스팅을 통해 서로 다른 미디어 유형을 균일하게 처리하는 방법과 다운캐스팅을 통해 고유한 기능에 접근하는 방법을 확인해 보세요!

치트 시트

Java에서 업캐스팅(upcasting)은 상속 계층 구조를 따라 위로 이동하며 자동으로 발생합니다. 자식 객체는 부모 타입 변수에 할당될 수 있습니다.:

Dog dog = new Dog();
Animal animal = dog;  // 업캐스팅 - 자동

업캐스팅을 하면 객체는 여전히 내부적으로 자식 타입임에도 불구하고 부모 클래스에 정의된 메서드에만 접근할 수 있습니다.

다운캐스팅(downcasting)은 부모 참조를 다시 자식 타입으로 변환합니다. 이는 명시적 캐스팅이 필요합니다:

Animal animal = new Dog();  // 업캐스팅
Dog dog = (Dog) animal;     // 다운캐스팅 - 명시적 캐스팅 필요
dog.bark();                 // 이제 Dog 메서드에 접근할 수 있습니다

다운캐스팅은 위험합니다. 만약 객체가 실제로 캐스팅하려는 타입이 아니라면, Java는 런타임에 ClassCastException을 발생시킵니다:

Animal animal = new Cat();
Dog dog = (Dog) animal;  // 컴파일은 되지만, 런타임에 오류가 발생합니다!

컴파일러는 선언된 타입만 보기 때문에 이 오류를 잡아낼 수 없습니다. 실제 객체 타입은 프로그램이 실행될 때만 알 수 있습니다.

직접 해보기

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // 입력 읽기
        String songTitle = scanner.nextLine();
        String artistName = scanner.nextLine();
        String podcastTitle = scanner.nextLine();
        int episodeNumber = scanner.nextInt();
        
        // TODO: Song 객체를 생성하고 Media 참조로 업캐스팅하기
        
        // TODO: Media 참조에서 play() 호출하기 (다형성 실습)
        
        // TODO: Media 참조를 다시 Song으로 다운캐스팅하기
        
        // TODO: Song 참조에서 showArtist() 호출하기
        
        // TODO: Podcast 객체를 생성하고 Media 참조로 업캐스팅하기
        
        // TODO: Media 참조에서 play() 호출하기
        
        // TODO: Media 참조를 다시 Podcast로 다운캐스팅하기
        
        // TODO: Podcast 참조에서 showEpisode() 호출하기
    }
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨