Javaの基礎を理解した皆さんに、さらに理解を深めるための問題を紹介します。
問題
次のクラス階層を利用して、プログラムが正しく実行された場合の出力を選んでください。
class Vehicle {
void start() {
System.out.println("Vehicle is starting");
}
}
class Car extends Vehicle {
@Override
void start() {
System.out.println("Car is starting");
}
}
public class Main {
public static void main(String[] args) {
Vehicle myCar = new Car();
myCar.start();
}
}
選択肢
- A. Vehicle is starting
- B. Car is starting
- C. コンパイルエラーが発生する
- D. 実行時エラーが発生する
答えと解説
回答を見る
答え
B. Car is starting
解説
解説のポイント:
- オーバーライドと動的バインディング
- オブジェクト型と実際のクラス型の役割
オーバーライドと動的バインディングは、Javaのオブジェクト指向プログラミングの基礎です。オーバーライドは、スーパークラスのメソッドをサブクラスで新たに定義し直すことを指します。このとき、多くのオブジェクト指向プログラミング言語では、呼び出すメソッドはプログラムの実行時に決定されます。
このプログラムでは、変数myCar
は型としてVehicle
を持っていますが、実体はCar
のオブジェクトです。myCar.start()
が呼ばれると、Javaは実行時にmyCar
が参照している実際のオブジェクト(Car
)のstart()
メソッドを呼び出します。そのため、出力は「Car is starting」となります。
基本説明
Javaのメソッド呼び出しは通常、クラスで定義されたメソッドが実行されるのではなく、オブジェクトが持つメソッドが実行されます。これは、オブジェクト指向プログラミングの動的バインディングという特徴です。
誤答理由
選択肢A「Vehicle is starting」を選んだ人は、型の宣言を重視し実際のオブジェクト型を見逃しています。Javaでは、変数が持つ型ではなく、実際のオブジェクトが持つメソッドが呼ばれることを理解していない可能性があります。選択肢CやDを選んだ人は、Javaのオーバーライドやキャストに誤解があるかもしれません。
つまずきポイント
初心者が誤りやすいポイントは、「変数型と実際のオブジェクト型の違い」「オーバーライドされているメソッドの動的バインディング」を理解していないことです。これにより、型に基づく基底クラスのメソッドが呼ばれるとの誤解を生みがちです。
発展知識
Javaのオブジェクト型と実際のクラス型の理解は、ポリモーフィズムの基礎です。ポリモーフィズムは柔軟で拡張性の高いコードを書くために重要です。Javaでは、オブジェクトが具体的な型にキャストされていなくても、宣言した型のメソッドが呼び出されたかのように動作します。しかし、実際には実体化されたオブジェクトのメソッドが動的に呼び出されることになります。