クラス型変数のキャスト

Revised: Jan./4th/2002: Since: Dec./30th/2001

前節で見た通り、サブクラスはスーパークラスを含んでいるので、サブクラス型のオブジェクトを参照する変数はスーパークラス型の変数に代入できます。つまり、サブクラスのインスタンスへの参照が、スーパークラス型変数にコピーできると言うことです。

その逆に、スーパークラスのオブジェクトを参照する変数は、サブクラス型の変数に代入できるとは限りません。出来る場合であっても、明示的な型変換つまりキャストが必要です。

  SuperClass
     A  |                      O.K.: SubClass ------> SuperClass
O.K. |  | NO or Cast
     |  |                NO or Cast: SuperClass ----> SubClass
     |  V
   SubClass

継承関係に限らず、通常は異なる参照型変数間の代入にはキャストが必要です。基本データ型の変数のキャストと同じです。

サンプル

  1. サブクラスのインスタンスを作り、
  2. サブクラス型変数 objKo に参照を代入します。
  3. このサブクラス型変数をスーパークラス型変数 objOya に代入しています
  4. このスーパークラス型変数をキャストして、別のサブクラス型変数 objOyaToKo に代入し直しています。

objOya が参照している実体であるインスタンスは、サブクラスからインスタンス化されているので、 objOya から使えないだけで、サブクラスのメソッドも持っています。キャストすることで、サブクラスで定義されたメソッドも使えるようになるはずです。

class TestCastObj {
	public static void main(String[] args) {
		//インスタンス化
		Ko objKo=new Ko();
		//参照の代入
		Oya objOya=objKo;
		objOya.getMsgOya();
//		objOya.getMsgKo();
		//Koクラス型変数定義
		Ko objOyaToKo;
		//キャスト
		objOyaToKo=(Ko)objOya;
		objOyaToKo.getMsgKo();
	}
}
class Oya {
	void getMsgOya() {
		System.out.println("親クラス。");
	}
}
class Ko extends Oya {
	void getMsgKo() {
		System.out.println("子クラス。");
	}
}

参照している実体はサブクラスからのものでも、変数の型によって見える範囲が異なるので、 objOya.getMsgKo() は使えません。しかし、見えていないだけで、参照先の実体は getMasKo() も持っているので、キャストにより変数の型を変えるだけで利用できるようになります。

C:\Java>javac TestCastObj.java
C:\Java>java TestCastObj
親クラス。
子クラス。

サンプル

Object クラスが全てのクラスのスーパークラスなので、この型の変数は任意のクラス型の変数を代入できます。この性質を利用して、任意のクラス型の値を引数にとれるメソッドが作れます。

ObjTest.java:

class ObjStore {
	private Object obj;
	public void setObj(Object arg) {
		obj = arg;
	}
	public Object getObj() {
		return obj;
	}
}
class ObjTest {
	public static void main(String[] args) {
		//テスト用のオブジェクト
		String str = new String("Hello!");
		//ObjStoreクラスのオブジェクト
		ObjStore perm = new ObjStore();
		//参照型変数のメソッド呼び出し代入
		perm.setObj(str);
		//メソッドの戻り値のキャスト
		String str2 = (String)perm.getObj();
		System.out.println(str);
		System.out.println(str2);
	}
}

setObj() メソッドは、引数の型が Object 型に定義されていますので、任意のクラス型の変数が引数として可能です。但し、受け取られるときに Object 型に自動型変換されます。

Object 型に自動型変換されたオブジェクトを getObj() でゲットしますが、戻り値はやはり Object 型です。しかし、このオブジェクトは自分でセットしたものであり、型が String であると分かっているので、キャストして String 型に戻してから受け取っています。

C:\Java>javac ObjTest.java
C:\Java>java ObjTest
Hello!
Hello!
C:\Java>

このサンプルは、標準クラスライブラリである Vector クラスを簡単にしたものに過ぎません。このクラスは可変長の配列を作りますが、その要素は Object 型で定義されています。どんなクラス型の参照でも代入できますが、受け取るときも Object 型で戻ってくるので、 Vector クラス型オブジェクトの要素をオブジェクトとして利用するときには、適切にキャストする必要があります。



Copyright © 2001 SUGAI, Manabu. All Rights Reserved.