こんにちは!前回はコンストラクターについて説明し、コンストラクターについて多くのことを学びました。ここで、基底クラスのコンストラクターなどについて説明します。基本クラスとは何ですか? 実際、Java では、いくつかの異なるクラスが共通の起源を持つことができます。 これを継承と呼びます。複数の子孫クラスが 1 つの共通の祖先クラスを持つことができます。たとえば、クラス
Animal
(動物) があると想像してください。
public class Animal {
String name;
int age;
}
たとえば、 2 つの子孫クラス (Cat
と )を作成できますDog
。これは、キーワード を使用して行われますextends
。
public class Cat extends Animal {
}
public class Dog extends Animal {
}
これは将来的に役立つかもしれません。たとえば、タスクがネズミを捕まえることである場合、プログラム内にオブジェクトを作成しますCat
。タスクがスティックの後に実行される場合は、 オブジェクト を使用しますDog
。そして、動物病院をシミュレートするプログラムを作成すると、クラスと連携して動作しますAnimal
(犬と猫の両方を治療できるようになります)。将来のために、オブジェクトを作成するときは、その基本クラスのコンストラクターが最初に呼び出され、その後、作成しているオブジェクトであるクラス自体のコンストラクターが呼び出されるということを覚えておくことが非常に重要です。つまり、オブジェクトを作成するときは、Cat
クラス コンストラクターが最初に機能しAnimal
、次にコンストラクターが機能しますCat
。これを確認するために、コンストラクターを追加してCat
コンソールAnimal
に出力しましょう。
public class Animal {
public Animal() {
System.out.println("Animal constructor completed");
}
}
public class Cat extends Animal {
public Cat() {
System.out.println("The constructor Cat worked!");
}
public static void main(String[] args) {
Cat cat = new Cat();
}
}
コンソール出力:
Отработал конструктор Animal
Отработал конструктор Cat!
確かに、これがすべての仕組みです。それはなんのためですか?たとえば、2 つのクラスの共通フィールドの重複を避けるためです。たとえば、すべての動物には心臓と脳がありますが、すべての動物に尻尾があるわけではありません。すべての動物に共通のフィールドを親クラスbrain
で宣言し、フィールドをサブクラスで宣言できます。次に、 class のコンストラクターを作成し、3 つのフィールドすべてを渡します。 heart
Animal
tail
Cat
Cat
public class Cat extends Animal {
String tail;
public Cat(String brain, String heart, String tail) {
this.brain = brain;
this.heart = heart;
this.tail = tail;
}
public static void main(String[] args) {
Cat cat = new Cat("Brain", "Heart", "Tail");
}
}
注意してください:クラスにはフィールドと がCat
ありませんが、コンストラクターは正常に機能します。これらのフィールドは、基本クラスから「プルアップ」されました。子孫クラスは基本クラスのフィールドにアクセスできるため、それらのフィールドはクラス内で表示されます。したがって、クラス内でこれらのフィールドを複製する必要はありません。クラスから取得できます。さらに、子孫クラスのコンストラクター内で基本クラスのコンストラクターを明示的に呼び出すことができます。基本クラスは「スーパークラス」とも呼ばれ、Java がこのキーワードを使用するのはこのためです。前の例では brain
heart
Animal
Cat
Cat
Animal
super
public Cat(String brain, String heart, String tail) {
this.brain = brain;
this.heart = heart;
this.tail = tail;
}
親クラスの各フィールドを個別に割り当てました。実際には、これを行う必要はありません。親クラスのコンストラクターを呼び出して、必要なパラメーターを渡すだけで十分です。
public class Animal {
String brain;
String heart;
public Animal(String brain, String heart) {
this.brain = brain;
this.heart = heart;
}
public class Cat extends Animal {
String tail;
public Cat(String brain, String heart, String tail) {
super(brain, heart);
this.tail = tail;
}
public static void main(String[] args) {
Cat cat = new Cat("Brain", "Heart", "Tail");
}
}
コンストラクターでは、Cat
コンストラクターを呼び出しAnimal
、2 つのフィールドをコンストラクターに渡しました。明示的に初期化する必要があるのは 1 つのフィールドだけです (存在しtail
ませAnimal
ん)。オブジェクトが作成されるときに、親クラスのコンストラクターが最初に呼び出されるという話を覚えていますか? したがって、単語がsuper()
コンストラクター内で常に最初に来る必要があるのはこのためです。そうしないと、コンストラクターのロジックが壊れ、プログラムでエラーが生成されます。
public class Cat extends Animal {
String tail;
public Cat(String brain, String heart, String tail) {
this.tail = tail;
super(brain, heart);//error!
}
public static void main(String[] args) {
Cat cat = new Cat("Brain", "Heart", "Tail");
}
}
コンパイラは、子孫クラスのオブジェクトを作成するときに、基本クラスのコンストラクターが最初に呼び出されることを認識しています。この動作を手動で変更しようとしても、変更は許可されません。
オブジェクトを作成するプロセス。
Animal
上では、基本クラスと親クラス、およびを使用した例を見てきましたCat
。ここで、これら 2 つのクラスを例として使用して、オブジェクトの作成と変数の初期化のプロセスを見ていきます。変数には静的変数とインスタンス変数(非静的変数)があることがわかっています。また、基本クラスにはAnimal
独自の変数があり、子孫クラスにCat
は独自の変数があることもわかります。Animal
わかりやすくするCat
ために、クラスに静的変数を 1 つ追加しましょう。animalCount
クラス変数はAnimal
地球上の動物種の総数、変数はcatsCount
猫の種の数になります。さらに、両方のクラスのすべての非静的変数に開始値を割り当てます (その後、コンストラクターで変更されます)。
public class Animal {
String brain = "The initial value of brain in the Animal class";
String heart = "The initial value of heart in the Animal class";
public static int animalCount = 7700000;
public Animal(String brain, String heart) {
System.out.println("The constructor of the Animal base class is being executed");
System.out.println("Have the variables of the Animal class already been initialized?");
System.out.println("The current value of the static variable animalCount = " + animalCount);
System.out.println("Current value of brain in class Animal = " + this.brain);
System.out.println("Current value of heart in class Animal = " + this.heart);
System.out.println("Have the variables of the Cat class already been initialized?");
System.out.println("The current value of the static variable catsCount = " + Cat.catsCount);
this.brain = brain;
this.heart = heart;
System.out.println("Animal base class constructor completed!");
System.out.println("Current value of brain = " + this.brain);
System.out.println("Current value of heart = " + this.heart);
}
}
public class Cat extends Animal {
String tail = "The initial value of tail in the Cat class";
static int catsCount = 37;
public Cat(String brain, String heart, String tail) {
super(brain, heart);
System.out.println("The constructor of the Cat class has started (the Animal constructor has already been executed)");
System.out.println("The current value of the static variable catsCount = " + catsCount);
System.out.println("Current value tail = " + this.tail);
this.tail = tail;
System.out.println("Current value tail = " + this.tail);
}
public static void main(String[] args) {
Cat cat = new Cat("Brain", "Heart", "Tail");
}
}
Cat
そこで、から継承した クラスの新しいオブジェクトを作成しますAnimal
。詳細なコンソール出力をプログラムに追加して、何がどのような順序で起こるかを見てみましょう。これは、オブジェクトを作成した結果としてコンソールに出力されるものですCat
。
Выполняется конструктор базового класса Animal
Были ли уже проинициализированы переменные класса Animal?
Текущее meaning статической переменной animalCount = 7700000
Текущее meaning brain в классе Animal = Изначальное meaning brain в классе Animal
Текущее meaning heart в классе Animal = Изначальное meaning heart в классе Animal
Были ли уже проинициализированы переменные класса Cat?
Текущее meaning статической переменной catsCount = 37
Конструктор базового класса Animal завершил работу!
Текущее meaning brain = Мозг
Текущее meaning heart = Сердце
Конструктор класса Cat начал работу (конструктор Animal уже был выполнен)
Текущее meaning статической переменной catsCount = 37
Текущее meaning tail = Изначальное meaning tail в классе Cat
Текущее meaning tail = Хвост
これで、新しいオブジェクトの作成時に変数が初期化され、コンストラクターが呼び出される順序が明確にわかります。
-
基本クラス( ) の静的変数が初期化されます。この例では、クラス変数には値 7700000 が割り当てられます。
Animal
animalCount
Animal
-
子孫クラス( ) の静的変数が初期化されます。注意してください - 私たちはまだコンストラクター内にいますが、コンソールにはすでに次のように表示されています。
Cat
Animal
Выполняется конструктор базового класса Animal Были ли уже проинициализированы переменные класса Animal? Текущее meaning статической переменной animalCount = 7700000 Текущее meaning brain в классе Animal = Изначальное meaning brain в классе Animal Текущее meaning heart в классе Animal = Изначальное meaning heart в классе Animal Были ли уже проинициализированы переменные класса Cat? Текущее meaning статической переменной catsCount = 37
-
次に、基本クラスの非静的変数が初期化されます。具体的には初期値を割り当て、コンストラクターで新しい値に変更します。コンストラクターはまだ作業を完了していませんが、初期値はすでに割り当てられています。
Animal
brain
heart
Выполняется конструктор базового класса Animal Были ли уже проинициализированы переменные класса Animal? Текущее meaning статической переменной animalCount = 7700000 Текущее meaning brain в классе Animal = Изначальное meaning brain в классе Animal Текущее meaning heart в классе Animal = Изначальное meaning heart в классе Animal
-
基本クラスのコンストラクターが動作を開始します。
このステージは連続して 4 番目にすぎないことはすでに確認しました。最初の 3 つのポイントでは、コンストラクターが動作を開始する時点で、
Animal
多くの変数にすでに値が割り当てられています。 -
子クラスの非静的フィールドを初期化しています( )。
Cat
それはデザイナーが
Cat
仕事を始める前に起こります。彼が仕事を始めた時点では、変数に
tail
はすでに値が含まれていました。Конструктор класса Cat начал работу (конструктор Animal уже был выполнен) Текущее meaning статической переменной catsCount = 37 Текущее meaning tail = Изначальное meaning tail в классе Cat
-
子孫クラスのコンストラクターが呼び出されます。
Cat
GO TO FULL VERSION