今日は抽象クラスについて問題を解きましょう。
問題
次のプログラムを見て、正しい出力を選んでください。
abstract class Vehicle {
abstract void start();
}
class Car extends Vehicle {
void start() {
System.out.println("Car starts");
}
}
public class Main {
public static void main(String[] args) {
Vehicle myVehicle = new Car();
myVehicle.start();
}
}
選択肢
- A. Car starts
- B. コンパイルエラー
- C. 実行時エラー
- D. 何も出力されない
答えと解説
回答を見る
答え
A. Car starts
解説
解説のポイント:
- 抽象クラスと抽象メソッド
- 継承とオーバーライドの基本
Javaにおける抽象クラスは、部分的に実装されたクラスであり、少なくとも1つの抽象メソッドを含んでいます。抽象メソッドは、サブクラスによって具現化(オーバーライド)される必要があります。
このコードでは、Vehicle
クラスは抽象クラスで、その中にはstart()
という抽象メソッドがあります。Car
クラスはVehicle
を継承し、start()
メソッドを具体的に実装しています。
プログラムの実行時に、Vehicle
型の変数myVehicle
にCar
オブジェクトを代入しています。このとき、myVehicle.start()
が呼び出され、実際にはCar
クラスのstart()
メソッドが実行され、「Car starts」という出力が得られます。
基本説明
抽象クラスは、完全なオブジェクトを持たないクラスのひな型のようなものです。抽象メソッドを含むことができ、これらのメソッドは必ずサブクラスで具体的に実装されなければなりません。このため、抽象クラス自体は直接インスタンス化できません。
例えば、抽象クラスVehicle
は車両の構造を定義していますが、具体的な動作はCar
や他の具体的な車両クラスに任されています。このように、抽象クラスは共通の構造を提供しつつ、各クラスに独自の具体性を持たせるのに便利です。
誤答理由
選択肢BとCを誤答として選ぶのは、抽象クラスが理解できていなかったり、抽象メソッドのオーバーライドを忘れている場合が多いです。Javaでは、抽象メソッドがオーバーライドされないとコンパイルエラーになりますが、この問題のケースでは正しくオーバーライドされているため、正常に動作します。
また、プログラムは正しくコンパイルと実行が可能であるため、実行時にエラーが発生することもありません。
つまずきポイント
抽象クラスとそのメソッドの役割をはっきりと理解していないと、オーバーライドすべき部分を見落とすことがあります。この場合、まずは抽象クラスが与える共通の「骨組み」は何かということを把握し、サブクラスで具体化するメソッドに集中する必要があります。
抽象クラス自体をインスタンス化しようとしてエラーを出すこともよくあるミスです。抽象クラスはそのままでは使えない、ということを常に意識しましょう。
発展知識
抽象クラスとインターフェースの違いを理解すると、Javaの設計思想をより深く理解できます。抽象クラスは一部実装を提供するため複数継承ができませんが、インターフェースはすべてのメソッドが抽象的で、多重継承が可能です。
また、Java 8以降ではインターフェースにもデフォルトメソッドを定義できるようになり、さらに柔軟な設計が可能になりました。このような進化を把握することで、オブジェクト指向プログラミングの幅を広げることができます。