教本に沿ってやってみたシリーズ、『第12章』。
≪使用教材≫スッキリわかるJava入門 第3版 スッキリわかるシリーズ
多態性の基本
あるものをざっくり分類したり、ざっくり捉える概念。
下記のように大まかな括りとして、HeroインスタンスをCharacter型に代入できる。
但し、ヒーロー=キャラクターのように絵に描いてみて嘘にならないもの。突拍子のない代入はエラーになる。
Character c = new Hero;
下記はabstractを持つCharacterクラスを継承したWizardクラスを代入しようと試みようとしている例である。抽象クラスインタフェースはインスタンス化はできないが、型として使用することは可能だ。
Character c = new Wizard();
ただし、子クラス独自のフィールドを呼び出そうとするとエラーが発生する。
抽象クラスCharacterを継承したWizardを、ざっくりキャラクターの一種とみなしてインスタンスを代入しているため、Wizardを個別に判定できず独自のフィールドを呼び出すことができない。
フィールドの中身をどうしても生成したインスタンスcに使わせたい場合は、「c = characterの一種」でwizardを捉えている現状から、厳密に「wizard = c」であると書き換える必要がある。通常の演算子では矛盾が生じていると判定されエラーになってしまうが、キャスト演算子で強制代入することで記述自体は可能である。しかし、曖昧な型に中身のしっかり成立したものを代入しようとしているため、コンパイルはできてもエラーは免れない。この失敗の可能性のあるキャストをダウンキャストという・
Character c = new Wizard();
Wizard w = (Wizard)c; // ダウンキャスト
- interface演算子
ダウンキャスト時、エラーが出るかどうかを実行前に判定してくれる砦。
if (c instanceof SuperHero ){ // interface演算子
//「もし、SuperHeroをcと見なして大丈夫なら…」
SuperHero h = (SuperHero)c;
h.fly();
}
多態性+配列
多態性のメリットは複数のインスタンスを同一視できること。
例えばざっくりCharacterとみなせる(継承している)クラスを対象にまとめて処理を行いたい場合は…
- 配列で「Character」インスタンス作成後、forで処理をループさせる
public class Main {
public static void main(String[] args) {
Character[] c = new Character[5];
c[0] = new Hero();
c[1] = new Hero();
c[2] = new Thief();
c[3] = new Wizard();
c[4] = new Wizard();
for(Character ch : c) {
ch.hp += 50;
}
}
}
同一メソッドで配列定義した複数の「monster」インスタンスを受け取れるように定義する。
- ざっくり引数でメソッドを定義
public class Main{
public static void main(String[] args) {
Hero h = new Hero();
Slime s = new Slime();
Goblin g =new Goblin();
h.attack(s);
h.attack(g);
}
}
class Slime extends Monster{
int hp;
}
class Hero extends Character {
public void attack(Monster m) {
System.out.println(this.name + "の攻撃!");
System.out.println("敵に10ポイントのダメージをあたえた!");
m.hp -= 10;
}
}
同一の指示でインスタンスごとに異なる動きをさせる。
- 配列でインスタンス化後、ざっくり型でメソッドを呼び出す。
public class Main{
public static void main(Stiring[] args) {
Monster[] monsters = new Monster[3];
monster[0] = new Slime();
monster[1] = new Goblin();
monster[2] = new DeathBat();
for (Monster m : monseters) {
m.run();
}
}
}
class Monster {
String name;
int hp;
void run() {
System.out.println(this.name + "は逃げ出した!");
}
}
class slime extends Monster{
void run() {
System.out.println(this.name + "体をうねらせて逃げ出した!");
}
}
class Goblin{…