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
継承関係に限らず、通常は異なる参照型変数間の代入にはキャストが必要です。基本データ型の変数のキャストと同じです。
objKo
に参照を代入します。objOya
に代入しています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
クラス型オブジェクトの要素をオブジェクトとして利用するときには、適切にキャストする必要があります。