多態性(ポリモーフィズム)
「インスタンスをあいまいに捉える」
継承によりis-aの関係が成立しているなら、インスタンスを親クラス型の変数に代入することができる
SuperHero h = new SuperHero();
通常のSuperHeroインスタンス
Character c = new SuperHero();
SuperHeroクラスの親クラスにCharacterを持っている前提
あいまいな型の箱へのインスタンスの代入
public class Main {
public static void main(String[] args) {
Wizard w = new Wizard();
Character c = w; // Character型の箱にいれる
Matango m = new Matango();
c.name = "魔法使い";
c.attack(m); //呼び出せる
c.fireball(m); //エラーになる
}
}
・箱の中身(Character c)がWizardであることを忘れてしまう
・attack()だけ呼び出せるのは、他のキャラクターはattackを持っているため
(どのキャラクターもattack()を持っている前提)
・fireball()が呼び出せなったのは、他のキャラクターがfireball()を持っていないから(持っているとは限らない為)エラーになる
・確実に言えることは、箱に入っているのはキャラクターの一種であることだけわかる
強制的にWizardを呼び出す方法(ダウンキャスト)
Character c = new Wizard();
Wizard w = c; //エラーになる
プログラムを1行ずつ解釈、翻訳する為、2行目のcがWizardとは確定できない為。
Character c = new Wizard();
Wizard w = (Wizard)c; //強制的な型変換を指示する
メソッドを呼び出せた場合に動く処理
Monster(親)クラスをSlime(子)クラスが継承してる
Monster System.out.println("モンスターは逃げ出した。");
Slime System.out.println("スライムは逃げ出した。");
public class Main {
public static void main(String[] args) {
Slime s = new Slime();
Monster m = new Slime();
s.run();
m.run();
}
}
実行結果
スライムは逃げ出した s.run()の結果
スライムは逃げ出した m.run()の結果
実際の結果は中身の型(Slime())によって決まる、箱の型(Monster m)は結果には関係ない
ダウンキャスト失敗(ClassCastException)
Character c = new Wizard();
Hero h = (Hero)c;
コンパイルに成功するが、動作させるとエラー
「嘘の構図」になっている為
安全にキャストできるか判断する(instanceof演算子)
if(c instanceof Wizard) { //もしcの中身がWizardと見なして大丈夫なら
Wizard w = (Wizard)c; //Wizardと見なせ
w.fly();
}