導入
Animal の sound() は、実際には Dog や Cat が必ずオーバーライドするので、親クラスに書いた中身は一度も使われません。意味のない実装を書くくらいなら、「中身は書かないが、必ずオーバーライドしてね」と強制できたら便利です。
説明
抽象クラス(abstract class) は、それ自体は インスタンス化できない クラスです。中に 抽象メソッド(abstract method) ――中身({ })を持たないメソッドの宣言だけを書くことができ、サブクラスに実装を 強制 できます。
public class Main {
public static void main(String[] args) {
Animal d = new Dog();
Animal c = new Cat();
d.sound();
c.sound();
}
}
abstract class Animal {
abstract void sound();
}
class Dog extends Animal {
@Override
void sound() {
System.out.println("ワン");
}
}
class Cat extends Animal {
@Override
void sound() {
System.out.println("ニャー");
}
}
abstract class Animal { ... }… クラス宣言にabstractをつけます。new Animal()はできません(抽象クラスは「設計図の下書き」であり、そのままでは実体化できないためです)。abstract void sound();… 中身のないメソッド宣言。Animalを継承するクラスは、必ずsound()をオーバーライドしなければなりません。書き忘れるとコンパイルエラーになります。
「意味のないダミー実装」を書く必要がなくなり、かつ「サブクラスは必ず実装すること」を型のレベルで強制できるのが抽象クラスの利点です。
やってみよう
下のエディタを実行して、Dog と Cat がそれぞれ sound() を実装していることを確認しましょう。Animal の sound() に中身を書こうとするとどうなるか(abstract メソッドには中身を書けない)も考えてみてください。
演習
Bird extends Animal を作り、sound() を "チュンチュン" と実装してください。main で Animal b = new Bird(); として sound() を呼んでください。
ヒント1を見る
class Bird extends Animal { @Override void sound() { System.out.println("チュンチュン"); } }。
ヒント2を見る
main で Animal b = new Bird(); b.sound();。