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

広告

サブクラスのオブジェクトをサブクラス型の変数ではなく、スーパークラス型の変数に代入することをアップキャストといいます。アップキャストを利用すると、異なるサブクラスのオブジェクトでも同じスーパークラス型の変数で扱うことができるため、複数のオブジェクトをまとめて処理することができます。一方、スーパークラス型の変数をサブクラス型に変換することをダウンキャストといいます。ここではオブジェクト指向におけるアップキャストおよびダウンキャストの使用方法について解説します。

アップキャストとは

他のクラスを継承したクラスを定義し、そのオブジェクトを作成した場合、スーパークラス型の変数に代入することができます。このようにサブクラスのオブジェクトをスーパークラス型として扱うことをアップキャストといいます。

例として Product クラスを継承した Foods クラスを定義します。

class Product {
  public void showInfo() {
    System.out.println("製品です");
  }
}

class Foods extends Product {
  public void showInfo() {
    System.out.println("食料品です");
  }
}

Foods クラスのオブジェクトを new を使って作成したときに、 Foods 型の変数に代入するのではなく、スーパークラスである Product 型の変数に代入することができます。

public class Sample {
  public static void main(String[] args) {
    Product p = new Foods();
  }
}

このようにサブクラスである Foods クラスのオブジェクトをスーパークラス型として扱うことをアップキャストといいます。

このとき、 Foods クラスとのオブジェクトが作成されたあとで、そのオブジェクトへの参照が Product 型の変数に代入されます。

アップキャストした場合にできること

アップキャストを行うと、作成されたオブジェクトはサブクラスのものですが、変数の型はスーパークラスになります。アップキャストしたオブジェクトからは、スーパークラスで定義されているメソッドのみを呼び出すことができます。サブクラスでのみ定義されたメソッドは呼び出すことができません。

次の例を見て下さい。

public class Sample {
  public static void main(String[] args) {
    Product p = new Foods();
    p.showA();
    p.showB();
  }
}

class Product {
	// サブクラスでオーバーライドされたメソッド
  public void showA () {
    System.out.println("A");
  }

  // スーパークラスでのみ定義されたメソッド
  public void showB () {
    System.out.println("B");
  }
}

class Foods extends Product {
	// オーバーライドされたメソッド
  public void showA () {
    System.out.println("Sub-A");
  }

  // サブクラスで独自に定義したメソッド
  public void showC () {
    System.out.println("C");
  }
}

この場合、変数 p の型は Product 型なので、 Product クラスで定義されているメソッドしか呼び出すことができません。具体的にはメソッド showA と showB は呼び出すことができますが、サブクラスでのみ定義されているメソッド showC は呼び出すことはできません。

実際に呼び出されるメソッド

変数 p が参照しているオブジェクトはサブクラスのものなので、メソッドが呼び出された場合、サブクラスの方で定義されているメソッドが呼び出されます。よってメソッド showA を呼び出すと、サブクラスの方で定義されたメソッドが呼び出されるため "Sub-A" と表示されます。

またメソッド showB を呼び出すと "B" と表示されます。メソッド showA についてはサブクラスでオーバーライドされていませんが、クラスを継承した場合、スーパークラスで定義されているメソッドを引き継ぎますので、オーバーライドされていないメソッドについてはスーパークラスで定義されているメソッドがそのまま呼び出されます。

よって先ほどのサンプルを実際に実行すると、次のように表示されます。

Sub-A
B

このように変数の型は Product 型ですが、実際に作成されているオブジェクトは Foods クラスなので Foods クラスのメソッドが実行されます。

アップキャストの利用例

アップキャストはポリモーフィズムを利用するときによく使用されます。スーパークラス型の変数でサブクラスのオブジェクトをまとめて扱うことができるため、複数の種類のオブジェクトを同じ方法で処理することができます。

Product[] list = new Product[2];

list[0] = new Foods();
list[1] = new Gadgets();

for (Product p : list) {
  p.showInfo();
}

このようにスーパークラス型でオブジェクトを管理することで、異なる種類のオブジェクトでも同じ方法で処理することができます。

※ ポリモーフィズムについては「ポリモーフィズムとは」を参照されてください。

ダウンキャストとは

アップキャストした場合、スーパークラスで定義されているメソッドしか呼び出すことができません。このような場合に、スーパークラス型の変数をサブクラス型へ変換することで、サブクラスで定義されているメソッドを呼び出すことができるようになります。このような変換をダウンキャストといいます。

ダウンキャストは次のような書式で記述します。

サブクラス型 変数 = (サブクラス型) スーパークラス型の変数;

例えば Product クラスを継承したサブクラスが Foods クラスの場合、ダウンキャストは次のように記述します。

Product p = new Foods();
Foods f = (Foods)p;

このようにキャスト演算子を使用することで、スーパークラス型の変数をサブクラス型に変換することができます。

次の例を見て下さい。

public class Sample {
  public static void main(String[] args) {
    Product p = new Foods();
    Foods f = (Foods)p;
    f.showA();
    f.showB();
    f.showC();
  }
}

class Product {
	// サブクラスでオーバーライドされたメソッド
  public void showA () {
    System.out.println("A");
  }

  // スーパークラスでのみ定義されたメソッド
  public void showB () {
    System.out.println("B");
  }
}

class Foods extends Product {
	// オーバーライドされたメソッド
  public void showA () {
    System.out.println("Sub-A");
  }

  // サブクラスで独自に定義したメソッド
  public void showC () {
    System.out.println("C");
  }
}

Foods クラスのオブジェクトを Product 型の変数 p に代入しています。その後で (Foods)p のように記述することで、Foods 型へ変換しています。ダウンキャストを行うことで、スーパークラス型の変数が参照しているオブジェクトをサブクラス型として扱えるようになります。そのため、スーパークラスから継承しているメソッドに加えて、サブクラスでのみ定義されているメソッドも呼び出せるようになります。

先ほどのサンプルを実際に実行すると、次のように表示されます。

Sub-A
B
C

ダウンキャストするときの注意点

ダウンキャストを行う場合、変数が参照しているオブジェクトが実際にそのサブクラスのオブジェクトである必要があります。

例えば次のような場合を考えてみます。

Product p = new Product();
Foods f = (Foods)p;

この場合、変数 p が参照しているオブジェクトは Product クラスのオブジェクトです。そのため Foods 型へ変換することはできません。このように記述するとコンパイルエラーにはなりませんが、プログラムの実行時に ClassCastException が発生します。

そのため、ダウンキャストを行う前に、 instanceof 演算子を使ってオブジェクトが指定したクラスのオブジェクトかどうかを確認すると安全です。

Product p = new Foods();

if (p instanceof Foods) {
  Foods f = (Foods)p;
}

※ instanceof 演算子は次のページで解説します。

-- --

オブジェクト指向におけるアップキャストおよびダウンキャストの使用方法について解説しました。

( Written by Tatsuo Ikura )

プロフィール画像

著者 / TATSUO IKURA

これから IT 関連の知識を学ばれる方を対象に、色々な言語でのプログラミング方法や関連する技術、開発環境構築などに関する解説サイトを運営しています。