クラスの継承
ダウンキャスト
継承関係にあるクラスはキャストできます。
下位のクラスへのキャストをダウンキャストといいます。
Dog dog = (Dog)animal;
目次
1. ダウンキャストとは
継承関係にあるクラスはキャスト(型変換)が可能です。
下位のクラス(サブクラス側)に変換することをダウンキャストといいます。
重要
ダウンキャストは、
プリミティブ型のキャストと同じように、
インスタンスの前に (スーパークラス名)を付けます。
ダウンキャストは、暗黙的に行えません。
プリミティブ型のキャストと
同じ感じね。
2. ダウンキャストの例
以下のサンプルでは、Animal_01クラスをスーパークラスにして、
Dog_61、Cat_61、というサブクラスを作りました。
Dog_61、Cat_61、のインスタンスを、Animal_01型の配列に代入しています。
これがダウンキャストです。
//Animal_01.java
public class Animal_01{
protected static String = "生き物です。";
protected String name;
public Animal_01(){
this.name = "no_name";
}
public Animal_01(String name){
this.name = name;
}
public static void printGroup(){
System.out.println(group);
}
public void printName(){
System.out.println(name + "だぞ! ガオー!");
}
}
//Dog_61.java
public class Dog_61 extends Animal_01{
public Dog_61(String name){
super(name);
}
//以下オーバーライドしたメソッド
@Override
public void printName(){
System.out.println(name + "だワン!");
}
//追加したメソッド
public void printBow(){
System.out.println(name + "は棒には当たらないワン!");
}
}
//Cat_61.java
public class Cat_61 extends Animal_01{
public Cat_61(String name){
super(name);
}
//オーバーライドしたメソッド
@Override
public void printName(){
System.out.println(name + "なのにゃ!");
}
//追加したメソッド
public void printKoban(){
System.out.println(name + "は小判が欲しいのにゃ!");
}
}
ダウンキャストして、
サブクラス独自のメソッドを
実行した例だ。
//Driver_71.java
public class Driver_71{
public static void main(String[] args){
Animal_01[] animalArray = new Animal_01[9];
animalArray[0] = new Animal_01("ゴン太くん");
animalArray[1] = new Animal_01("ふなっしー");
animalArray[2] = new Animal_01("アニマル浜口");
animalArray[3] = new Dog_61("ヨーゼフ");
animalArray[4] = new Dog_61("パトラッシュ");
animalArray[5] = new Dog_61("白いお父さん");
animalArray[6] = new Cat_61("ニャース");
animalArray[7] = new Cat_61("ドラえもん");
animalArray[8] = new Cat_61("ニャンパス");
for(int i=0; i<animalArray.length; i++){
animalArray[i].printName();
}
//ここまでは Driver_61 と同じです。-----------------------------
System.out.println("-- dog --");
for(int i=3; i<6; i++){
Dog_61 dog = (Dog_61)animalArray[i]; //ダウンキャスト
dog.printBow(); //Dog_61クラス独自のメソッド
}
System.out.println("-- cat --");
for(int i=6; i<9; i++){
Cat_61 cat = (Cat_61)animalArray[i]; //ダウンキャスト
cat.printKoban(); //Cat_61クラス独自のメソッド
}
}
}
コマンドライン
>cd ws
ws>javac -encoding UTF-8 Driver_71.java
ws>java Driver_71
-- animal --
ゴン太くんだぞ! ガオー! printName
ふなっしーだぞ! ガオー! printName
アニマル浜口だぞ! ガオー! printName
ヨーゼフだワン! printName
パトラッシュだワン! printName
白いお父さんだワン! printName
ニャースなのにゃ! printName
ドラえもんなのにゃ! printName
ニャンパスなのにゃ! printName
-- dog --
ヨーゼフは棒には当たらないワン! printBow
パトラッシュは棒には当たらないワン!printBow
白いお父さんは棒には当たらないワン!printBow
-- cat --
ニャースは小判が欲しいのにゃ! printKoban
ドラえもんは小判が欲しいのにゃ! printKoban
ニャンパスは小判が欲しいのにゃ! printKoban
実はこの方法は
ちょっと使いづらい。
次を見てくれ。
3. キャスト先のインスタンスでないとダウンキャストできない
重要
キャスト先のインスタンスでないとダウンキャストできない。
例えば、Animal_01のインスタンスは、Dog_61クラスや、Cat_61クラスにキャストできません。
Driver_71 で、
i=3; i<6;
のように「狙い撃ち」していたのはこのためです。
まあ、
そうでしょうね。
//Driver_72NG.java
public class Driver_72NG{
public static void main(String[] args){
Animal_01 animal = new Animal_01("アニマル浜口");;
Cat_61 cat = (Cat_61)animal; //NGダウンキャスト
}
}
コマンドライン
>cd ws
ws>javac -encoding UTF-8 Driver_72NG.java
ws>java Driver_72NG
Exception in thread "main" java.lang.ClassCastException:
Animal_01 cannot be cast to Cat_61
at Driver_72NG.main(Driver_72NG.java:7)
え~、
Animal_01
キャンのっと ビー キャスト とぅ
Cat_61?
つまり、
アップキャストしたインスタンスを
戻すときに使うってことね?
ダウンキャストする場合には、
目的のクラスにダウンキャストできるか確認する必要があります。
共通のスーパークラスを持つサブクラスを複数利用する場合には、
後述の「インターフェイス」を使う方法もご検討ください。
きれいに書けると思います。
そう。
なのです。
4. instanceof 演算子でクラスを調べる
ダウンキャストがいまいち使いにくいのは、
アップキャストしたインスタンスが、目的のクラスにダウンキャストできるか判別する方法が必要だからです。
java.lang.ClassCastException をキャッチする方法も考えられますが、
事前に instanceof 演算子で、インスタンスのクラスを調べる方法もあります。
instanceof 演算子は、変数が目的のクラスであるか調べる演算子です。
目的のクラスであれば true
そうでなければ false
を返します。
スーパークラスの配列に、アップキャストしたインスタンスを代入しているとき、
各要素を instanceof 演算子で評価すれば、
ClassCastException を回避できます。
こういった使い方が
効率的に正しいのか
ちょっとよくわからない。
//Driver_73.java
public class Driver_73{
public static void main(String[] args){
Animal_01[] animalArray = new Animal_01[9];
animalArray[0] = new Animal_01("ゴン太くん");
animalArray[1] = new Animal_01("ふなっしー");
animalArray[2] = new Animal_01("アニマル浜口");
animalArray[3] = new Dog_61("ヨーゼフ");
animalArray[4] = new Dog_61("パトラッシュ");
animalArray[5] = new Dog_61("白いお父さん");
animalArray[6] = new Cat_61("ニャース");
animalArray[7] = new Cat_61("ドラえもん");
animalArray[8] = new Cat_61("ニャンパス");
for(int i=0; i<animalArray.length; i++){
animalArray[i].printName();
}
//ここまでは Driver_61 と同じです。-----------------------------
System.out.println("-- dog --");
for(int i=0; i<animalArray.length; i++){
if(animalArray[i] instanceof Dog_61){ //Dog_61クラスか判定
Dog_61 dog = (Dog_61)animalArray[i]; //ダウンキャスト
dog.printBow();
}
}
System.out.println("-- cat --");
for(int i=0; i<animalArray.length; i++){
if(animalArray[i] instanceof Cat_61){ //Cat_61クラスか判定
Cat_61 cat = (Cat_61)animalArray[i]; //ダウンキャスト
cat.printKoban();
}
}
}
}
コマンドライン
>cd ws
ws>javac -encoding UTF-8 Driver_73.java
ws>java Driver_73
-- animal --
ゴン太くんだぞ! ガオー! printName
ふなっしーだぞ! ガオー! printName
アニマル浜口だぞ! ガオー! printName
ヨーゼフだワン! printName
パトラッシュだワン! printName
白いお父さんだワン! printName
ニャースなのにゃ! printName
ドラえもんなのにゃ! printName
ニャンパスなのにゃ! printName
-- dog --
ヨーゼフは棒には当たらないワン! printBow
パトラッシュは棒には当たらないワン!printBow
白いお父さんは棒には当たらないワン!printBow
-- cat --
ニャースは小判が欲しいのにゃ! printKoban
ドラえもんは小判が欲しいのにゃ! printKoban
ニャンパスは小判が欲しいのにゃ! printKoban
まあ動けばいいか。
お疲れ様でした。