こんにちは!これまでの講義で、継承の概念については何度か簡単に触れてきました。今日はこのトピックについても触れますが、あまり深くは触れません。これについては後で詳しく説明しますが、今日は実際の例だけを見て、Java の 1 つの興味深い演算子について説明します。
Javaの継承
では、継承とは一体何でしょうか? 継承は、Java を含むプログラミングにおけるメカニズムであり、既存のクラスに基づいて新しいクラスを記述することができます。その後、子孫クラスは親クラスのフィールドとメソッドにアクセスできるようになります。なぜこれが必要なのでしょうか? たとえば、プログラム内でトラック、レーシング、セダン、ピックアップなどのいくつかのクラスの車を作成する必要があると想像してください。コードを書き始めなくても、これらのクラスには多くの共通点があることがわかります。すべての車には、モデル名、製造年、エンジン サイズ、最高速度などが含まれています。(言うまでもなく、すべてにホイールやその他の部品が付いています)。このような状況では、次のことができます。- これらのフィールドをクラスごとに作成し、新しい自動車クラスの作成時に追加します。
- すべてのマシンに共通のフィールドを親クラスに移動する
Car
と、特定のタイプのマシンのすべてのクラスがextends というCar
単語の使用を継承します。
public class Car {
private String model;
private int maxSpeed;
private int yearOfManufacture;
public Car(String model, int maxSpeed, int yearOfManufacture) {
this.model = model;
this.maxSpeed = maxSpeed;
this.yearOfManufacture = yearOfManufacture;
}
}
public class Truck extends Car {
public Truck(String model, int maxSpeed, int yearOfManufacture) {
super(model, maxSpeed, yearOfManufacture);
}
}
public class Sedan extends Car {
public Sedan(String model, int maxSpeed, int yearOfManufacture) {
super(model, maxSpeed, yearOfManufacture);
}
}
少なくとも、コードの不必要な重複は避けています。これは、プログラムを作成する際に常に努力すべきことです。さらに、シンプルでわかりやすいクラス構造を採用しています。すべてのマシンに共通のフィールドが 1 つのクラスに配置されています。たとえば、トラックに他の車にはない特定のフィールドがある場合、それらを で宣言できますTruck
。メソッドについても同様です。すべての車には、車の始動、アクセル/ブレーキなど、説明できるいくつかの共通の動作があります。これらの一般的なメソッドは一般的なクラスに配置できCar
、各特定の型の特定の動作は子孫クラスで記述することができます。
public class Car {
public void gas() {
//...gas
}
public void brake() {
//...brake
}
}
public class F1Car extends Car {
public void pitStop() {
//...only racing cars make pit stops
}
public static void main(String[] args) {
F1Car formula1Car = new F1Car();
formula1Car.gas();
formula1Car.pitStop();
formula1Car.brake();
}
}
すべての車に共通のメソッドをクラスに移動しましたCar
。しかし後継者層にはF1Car
、F1レーシングカーを説明する - レースでのみ行われ、特定の動作によって区別されるピットストップ(車の緊急メンテナンスのための停止)。
Java インスタンスオブ演算子
オブジェクトがクラスに基づいて作成されているかどうかを確認するために、Java には特別な演算子 - がありますinstanceof
。true
テストが true の場合、またはfalse
結果が false の場合は値を返します。車のクラスを例として使用して、それがどのように機能するかを見てみましょう。
public class Truck extends Car {
public static void main(String[] args) {
Truck truck = new Truck();
System.out.println(truck instanceof Car);
}
}
出力: trueクラスのオブジェクトがあり、すべてのトラックが自動車であるため、 演算子を使用してテストすると がinstanceof
返されました。このクラスはクラス の子孫であるため、すべてのトラックは共通の親である自動車に基づいて作成されます。演算子に注意してください。これはメソッド (「オブジェクトのインスタンス」) ではなく演算子であるため、ドットなしで書かれています。別の方法で試してみましょう: true
Truck
Truck
Car
instanceof
public static void main(String[] args) {
Car car = new Car();
System.out.println(car instanceof Truck);
}
出力: false このクラスCar
、およびそれに応じてそのオブジェクトは、クラスから派生しません。すべてのTruck
トラックは車ですが、すべての車がトラックであるわけではありません。オブジェクトはCar
クラスに基づいて作成されませんTruck
。もう 1 つの例:
public static void main(String[] args) {
Car car = new Car();
Truck truck = new Truck();
System.out.println(car instanceof Object && truck instanceof Object);
}
出力: True ここでのロジックも単純です。作成したクラスも含め、Java のすべてのクラスはクラスから来ています(ただし、クラス内にextends Object はObject
記述しません。このメカニズムはクラス内で暗黙的に行われます)。これがなぜ役立つのでしょうか、またどのような状況で役立つのでしょうか? 演算子の最も一般的な使用法は、メソッドのオーバーライドとして使用されます。たとえば、メソッドがクラスに実装される方法は次のとおりです。 instanceof
equals()
equals
String
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String) anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
このメソッドは、文字列と渡されたオブジェクトを比較する前に、渡されたオブジェクトが実際に文字列であるかどうかをチェックします。そうして初めて、彼は 2 つのオブジェクトのプロパティを比較し始めます。このチェックを行わないと、値フィールドと長さフィールドを持つオブジェクトをメソッドに渡して文字列と比較する可能性がありますが、これは当然ながら間違っています。
GO TO FULL VERSION