Animal
(động vật):
public class Animal {
String name;
int age;
}
Ví dụ: chúng ta có thể tạo cho nó 2 lớp con cháu - Cat
và Dog
. Điều này được thực hiện bằng cách sử dụng từ khóa extends
.
public class Cat extends Animal {
}
public class Dog extends Animal {
}
Điều này có thể hữu ích cho chúng tôi trong tương lai. Ví dụ: nếu nhiệm vụ là bắt chuột thì chúng ta sẽ tạo một đối tượng trong chương trình Cat
. Nếu nhiệm vụ là chạy theo một cây gậy thì chúng ta sử dụng đối tượng Dog
. Và nếu chúng ta tạo một chương trình mô phỏng một phòng khám thú y, nó sẽ hoạt động với cả lớp Animal
(để có thể chữa bệnh cho cả chó và mèo). Điều rất quan trọng cần nhớ trong tương lai là khi tạo một đối tượng, hàm tạo của lớp cơ sở của nó được gọi đầu tiên và chỉ sau đó hàm tạo của chính lớp đó, đối tượng mà chúng ta đang tạo, mới được gọi. Nghĩa là, khi tạo một đối tượng, Cat
hàm tạo của lớp sẽ hoạt động trước tiên Animal
, sau đó mới đến hàm tạo Cat
. Để đảm bảo điều này, hãy thêm vào hàm tạo Cat
và Animal
xuất ra bảng điều khiển.
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();
}
}
Đầu ra của bảng điều khiển:
Отработал конструктор Animal
Отработал конструктор Cat!
Quả thực, đây là cách mọi chuyện diễn ra! Nó dùng để làm gì? Ví dụ, để tránh trùng lặp các trường chung của hai lớp. Ví dụ, mọi con vật đều có trái tim và bộ não, nhưng không phải con vật nào cũng có đuôi. Chúng ta có thể khai báo các trường chung cho tất cả các loài động vật brain
trong heart
lớp cha Animal
và một trường tail
trong lớp con Cat
. Bây giờ chúng ta sẽ tạo một hàm tạo cho lớp Cat
, trong đó chúng ta sẽ chuyển cả 3 trường.
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");
}
}
Chú ý:hàm tạo hoạt động thành công, mặc dù lớp Cat
không có các trường brain
và heart
. Các trường này được “kéo lên” từ lớp cơ sở Animal
. Lớp con có quyền truy cập vào các trường của lớp cơ sở, vì vậy Cat
chúng hiển thị trong lớp của chúng ta. Do đó, chúng ta không cần Cat
sao chép các trường này trong lớp - chúng ta có thể lấy chúng từ lớp Animal
. Hơn nữa, chúng ta có thể gọi hàm tạo của lớp cơ sở một cách rõ ràng trong hàm tạo của lớp con. Lớp cơ sở còn được gọi là “ superclass ”, đó là lý do tại sao Java sử dụng từ khóa super
. Trong ví dụ trước
public Cat(String brain, String heart, String tail) {
this.brain = brain;
this.heart = heart;
this.tail = tail;
}
Chúng tôi đã chỉ định riêng từng trường trong lớp cha của chúng tôi. Trên thực tế, bạn không cần phải làm điều này. Chỉ cần gọi hàm tạo của lớp cha và truyền cho nó các tham số cần thiết là đủ:
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");
}
}
Trong hàm tạo, Cat
chúng ta đã gọi hàm tạo Animal
và truyền hai trường cho nó. Chúng tôi chỉ phải khởi tạo rõ ràng một trường - trường tail
này Animal
không có. Hãy nhớ chúng ta đã nói rằng khi một đối tượng được tạo, hàm tạo của lớp cha sẽ được gọi đầu tiên? Vì vậy, đây là lý do tại sao từ này super()
luôn phải đứng đầu trong hàm tạo! Nếu không, logic của hàm tạo sẽ bị hỏng và chương trình sẽ phát sinh lỗi.
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");
}
}
Trình biên dịch biết rằng khi tạo một đối tượng của lớp con, hàm tạo của lớp cơ sở sẽ được gọi đầu tiên. Và nếu bạn cố gắng thay đổi hành vi này theo cách thủ công, nó sẽ không cho phép điều đó.
Quá trình tạo ra một đối tượng.
Ở trên chúng ta đã xem xét một ví dụ với lớp cơ sở và lớp cha -Animal
và Cat
. Bây giờ, sử dụng hai lớp này làm ví dụ, chúng ta sẽ xem xét quá trình tạo một đối tượng và khởi tạo các biến. Chúng tôi biết rằng các biến là biến tĩnh và biến thể hiện (không tĩnh). Chúng ta cũng biết rằng lớp cơ sở Animal
có các biến riêng và lớp con Cat
có các biến riêng. Hãy thêm một biến tĩnh vào lớp cho Animal
rõ ràng . Cat
Biến animalCount
lớp Animal
sẽ là tổng số loài động vật trên trái đất và biến catsCount
sẽ là số lượng loài mèo. Ngoài ra, chúng ta sẽ gán giá trị bắt đầu cho tất cả các biến không tĩnh của cả hai lớp (sau đó sẽ thay đổi trong hàm tạo).
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");
}
}
Vì vậy, chúng ta tạo một đối tượng mới của lớp Cat
được kế thừa từ Animal
. Hãy thêm đầu ra bảng điều khiển chi tiết vào chương trình của chúng tôi để xem điều gì sẽ xảy ra và theo thứ tự nào. Đây là những gì sẽ được xuất ra bàn điều khiển sau khi tạo một đối tượng 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 = Хвост
Vì vậy, bây giờ chúng ta có thể thấy rõ thứ tự các biến được khởi tạo và các hàm tạo được gọi khi tạo một đối tượng mới:
-
Các biến tĩnh của lớp cơ sở ( ) được khởi tạo
Animal
. Trong trường hợp của chúng tôi, biếnanimalCount
lớpAnimal
được gán giá trị 7700000. -
Các biến tĩnh của lớp con ( ) được khởi tạo
Cat
. Hãy chú ý - chúng ta vẫn đang ở bên trong hàm tạoAnimal
và bảng điều khiển đã thông báo:Выполняется конструктор базового класса Animal Были ли уже проинициализированы переменные класса Animal? Текущее meaning статической переменной animalCount = 7700000 Текущее meaning brain в классе Animal = Изначальное meaning brain в классе Animal Текущее meaning heart в классе Animal = Изначальное meaning heart в классе Animal Были ли уже проинициализированы переменные класса Cat? Текущее meaning статической переменной catsCount = 37
-
Tiếp theo, các biến không tĩnh của lớp cơ sở được khởi tạo . Chúng tôi đã gán cụ thể cho chúng các giá trị ban đầu, sau đó các giá trị này sẽ được thay đổi thành giá trị mới trong hàm tạo. Hàm tạo
Animal
vẫn chưa hoàn thành công việc của mình nhưng các giá trị ban đầubrain
đãheart
được gán:Выполняется конструктор базового класса Animal Были ли уже проинициализированы переменные класса Animal? Текущее meaning статической переменной animalCount = 7700000 Текущее meaning brain в классе Animal = Изначальное meaning brain в классе Animal Текущее meaning heart в классе Animal = Изначальное meaning heart в классе Animal
-
Hàm tạo của lớp cơ sở bắt đầu hoạt động .
Chúng ta đã thấy rằng giai đoạn này chỉ là giai đoạn thứ tư: trong ba điểm đầu tiên, tại thời điểm hàm tạo bắt đầu hoạt động,
Animal
nhiều biến đã được gán giá trị. -
Đang khởi tạo các trường không tĩnh của lớp con (
Cat
).Nó xảy ra trước khi nhà thiết kế
Cat
bắt đầu làm việc.Vào thời điểm anh ấy bắt đầu làm việc, biến đó
tail
đã có giá trị:Конструктор класса Cat начал работу (конструктор Animal уже был выполнен) Текущее meaning статической переменной catsCount = 37 Текущее meaning tail = Изначальное meaning tail в классе Cat
-
Hàm tạo của lớp con được gọi là
Cat
GO TO FULL VERSION