マンガで分かる Java入門講座

第9章 クラスとオブジェクト2
9-5. 継承4 オブジェクトのキャスト

オブジェクトを、継承関係のあるオブジェクトの代わりに使う「キャスト」について説明します。

● あるクラスから別のクラスへのオブジェクトのキャストは不可能

 Javaでは、あるクラスのオブジェクトから別のクラスのオブジェクトへは、原則としてキャストを行うことはできません。

 それは、あるクラスと別のクラスのフィールドやメソッドが一致していないからです。そのため、そのまま同じクラスとして扱うことができないからです。

図)あるクラスから別のクラスへのオブジェクトのキャストは不可能
┏ClassA━━┓             ┏ClassB━━┓
┃     ┃             ┃     ┃
┃     ┃public          ┃     ┃public
┃     ┠─○a   ←────── ┃     ┠─○v
┃     ┠─○b   a b c() d()と  ┃     ┠─○w
┃     ┠─○c()  v w x() y()は  ┃     ┠─○x()
┃     ┠─○d()  一致しない   ┃     ┠─○y()
┗━━━━━┛             ┗━━━━━┛

● サブクラスからスーパークラスへのオブジェクトのキャストは可能

 あるクラスから別のクラスへのオブジェクトのキャストは不可能と書きましたが、例外があります。サブクラスとスーパークラスの間のキャストは可能です。

 ここではまずは、サブクラスからスーパークラスへのオブジェクトのキャストを扱います。これは問題なく行えます。

 なぜならば、サブクラスの中に、スーパークラスのフィールドとメソッドが全て含まれているからです。

図)サブクラスからスーパークラスへのオブジェクトのキャストは可能
                  ┏SubClass━━━━┓
┏SuperClass━┓          ┃┏SuperClass━┓┃
┃      ┃public  ←─── ┃┃      ┃┃public
┃      ┠─○a   aとb()が ┃┃      ┠──○a
┃      ┠─○b()  あるので ┃┃      ┠──○b()
┗━━━━━━┛     同じと  ┃┗━━━━━━┛┃
             みなせる ┃        ┃public
                  ┃        ┠─○x
                  ┃        ┠─○y()
                  ┗━━━━━━━━┛

● サブクラスからスーパークラスにキャストした際に参照されるフィールドやメソッド

 サブクラスからスーパークラスにキャストしたオブジェクトは、フィールドはスーパークラスのものが使われます。

 また、メソッドは、オーバーライドされていればサブクラスのものが、されていなければ通常通りにスーパークラスのものが使われます。

図)SuperClassにキャストした場合
┏SubClass━━━━━━━━┓
┃┏SuperClass━┓    ┃
┃┃      ┃public ┃
┃┃      ┠─★a  ┠─○a
┃┃      ┠─○b() ┠─★@Override b()
┃┃      ┠─★c() ┃
┃┗━━━━━━┛    ┃
┗━━━━━━━━━━━━┛

ソースコード)スーパークラス
package sample;

public class SuperClass {
    public int no = 1;

    public int getNo() {
        return no;
    }
}

ソースコード)サブクラス
package sample;

public class SubClass extends SuperClass {
    public int no = 9;

    @Override
    public int getNo() {
        return no * 2;
    }
}

ソースコード)キャストして使用
SubClass subClass = new SubClass();
System.out.println(subClass.no);       // 「9」と出力
System.out.println(subClass.getNo());  // 「18」と出力

SuperClass superClass = subClass;
System.out.println(superClass.no);       // 「1」と出力
System.out.println(superClass.getNo());  // 「18」と出力

● スーパークラスからサブクラスへのオブジェクトのキャスト

 スーパークラスからサブクラスへのオブジェクトのキャストは、実行時エラーになる場合と、そうでない場合があります。

 まず、エラーになる場合です。以下の例では、スーパークラスには、サブクラスで拡張されたフィールドやメソッドが含まれていません。そのため、そのまま使うことができず、エラーが発生します。

ソースコード)エラーになる場合
// 実行時にエラーになる  java.lang.ClassCastException
SuperClass superClass = new SuperClass();
SubClass subClass = (SubClass)superClass;

図)エラーになる場合
┏SubClass━━━━┓
┃┏SuperClass━┓┃           ┏SuperClass━┓
┃┃      ┃┃public  ←──── ┃      ┃public
┃┃      ┠──○a   xとy()が  ┃      ┠─○a
┃┃      ┠──○b()  ないので  ┃      ┠─○b()
┃┗━━━━━━┛┃     同じと   ┗━━━━━━┛
┃        ┃public  みなせない
┃        ┠─○x
┃        ┠─○y()
┗━━━━━━━━┛

 次にエラーにならない場合です。以下の例では、参照先のインスタンスがサブクラスのものなので、エラーは発生しません。

 ここで重要なのは、キャストしても変数の中身の情報が失われるわけではないということです。

ソースコード)エラーにならない場合
// 実行時にエラーにならない
SubClass   subClass1  = new SubClass()
SuperClass superClass = (SuperClass)subClass1;
SubClass   subClass2  = (SubClass)superClass;

図)エラーにならない場合
┏Sub ━━━┓      ┏Sub ‥‥‥┓      ┏Sub ━━━┓
┃┏Super ┓┃      :┏Super ┓:      ┃┏Super ┓┃
┃┃   ┃┃public  ←:┃   ┃:public  ←┃┃   ┃┃public
┃┃   ┠──○a    :┃   ┠──○a    ┃┃   ┠──○a
┃┃   ┠──○b()   :┃   ┠──○b()   ┃┃   ┠──○b()
┃┗━━━┛┃      :┗━━━┛:      ┃┗━━━┛┃
┃     ┃public   :     :public   ┃     ┃public
┃     ┠─○x    :     :─○x    ┃     ┠─○x
┃     ┠─○y()   :     :─○y()   ┃     ┠─○y()
┗━━━━━┛      ┗‥‥‥‥‥┛      ┗━━━━━┛

● メソッドの引数でサブクラスを使う

 メソッドの引数でクラスが指定されている場合は、そのサブクラスも全て利用することができます。

 これは、サブクラスはスーパークラスの代わりに利用できるからです。

ソースコード)メソッド
public void method(SuperClass sc) {
}

ソースコード)メソッドの引数でサブクラスを使う
SuperClass superClass = new SuperClass();
SubClass subClass = new SubClass();

method(superClass);  // 問題なし
method(subClass);    // 問題なし

この講座のマンガ部分は「箱人形マンガ(Box Comic) 」で作成しています。
作成:2013/06/03  更新:2015/08/09  [Permalink]