Menu
Coddy logo textTech

アップキャストとダウンキャスト

CoddyのJavaジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 30/87。

前のレッスンでは、親型の変数が子オブジェクトを保持できることを見ました。Animal myPet = new Dog()この代入はupcastingと呼ばれ、Dogは常にAnimalであるため、自動的に行われます。

アップキャストは継承階層を上に移動します。暗黙的に行われ、常に安全です。

Dog dog = new Dog();
Animal animal = dog;  // アップキャスティング - 自動

アップキャストすると、parent class で定義された methods にしかアクセスできません。オブジェクトの内部が依然として Dog であっても、子クラス固有の methods は非表示になります。

Downcastingは逆方向に進み、parent参照をchild型に戻します。常に安全とは限らないため、これはexplicit castを必要とします。

Animal animal = new Dog();  // アップキャスティング
Dog dog = (Dog) animal;     // ダウンキャスティング - 明示的なキャストが必要
dog.bark();                 // これでDogのメソッドにアクセスできる

Downcasting は危険です。オブジェクトが実際にはキャスト先の型でない場合、Java は実行時に ClassCastException をスローします。

Animal animal = new Cat();
Dog dog = (Dog) animal;  // コンパイルは通るが、実行時にクラッシュする!

コンパイラは宣言された型しか認識しないため、このエラーを検出できません。実際のオブジェクトの型がわかるのは、プログラムの実行時だけです。次のレッスンでは、ダウンキャストする前にオブジェクトの型を安全に確認する方法を学びます。

challenge icon

チャレンジ

簡単

upcasting と downcasting の両方の動作を示すメディアプレーヤーシステムを構築しましょう。メディア型の階層を作成し、parent と child の参照間で変換する練習をします。

コードを4つのファイルに分けて整理します。

  • Media.java: すべてのメディア型が共有する Base class を作成します。すべてのメディア項目には title field(String)があります。これを initialize する constructor、getter method getTitle()、および play() を呼び出して Playing: [title] を出力する method を含めます。
  • Song.java: Media を extends する class を作成します。Song には追加の artist field(String)があります。parent の initialize には super を使用します。play() を Override して Playing song: [title] by [artist] を出力します。showArtist() method を追加し、Artist: [artist] を出力します。
  • Podcast.java: Media を extends する別の class を作成します。Podcast には episode field(int)があります。play() を Override して Playing podcast: [title] - Episode [episode] を出力します。showEpisode() method を追加し、Episode: [episode] を出力します。
  • Main.java: メディア型を使って upcasting と downcasting を実演します。4つの入力、つまり曲のタイトル、アーティスト名、ポッドキャストのタイトル、エピソード番号を受け取ります。

    まず、Song を作成して Media reference に upcast します。この reference に対して play() を Call し、run-time polymorphism が動作する様子を確認します。

    次に、その Media reference を Song に downcast し、showArtist() を Call して child 固有の method に access します。

    続いて、Podcast を作成して Media reference に upcast します。この reference に対して play() を Call します。

    最後に、その Media reference を Podcast に downcast し、showEpisode() を Call します。

4つの入力、つまり曲のタイトル(String)、アーティスト名(String)、ポッドキャストのタイトル(String)、エピソード番号(int)を受け取ります。

出力には4行を表示します。曲について2行(play の出力とアーティスト情報)、ポッドキャストについて2行(play の出力とエピソード情報)です。upcasting によって異なるメディア型を統一的に扱える一方、downcasting によってそれぞれの固有の機能に access できることに注目してください。

自分で試してみよう

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腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: Javaオンラインコンパイラ