

Animal
ชั้นเรียน:
public class Animal {
String name;
int age;
}
เราสามารถประกาศคลาสลูกได้ 2 คลาส: Cat
และ Dog
ทำได้โดยใช้คำหลัก expands
public class Cat extends Animal {
}
public class Dog extends Animal {
}
เราอาจพบว่าสิ่งนี้มีประโยชน์ในอนาคต ตัวอย่างเช่น หากมีงานให้จับหนู เราจะสร้างวัตถุ Cat
ในโปรแกรมของเรา หากภารกิจคือการไล่ตามไม้เราจะใช้ Dog
วัตถุ และถ้าเราสร้างโปรแกรมที่จำลองคลินิกสัตวแพทย์ มันจะทำงานร่วมกับAnimal
ชั้นเรียน (และสามารถรักษาทั้งแมวและสุนัข) สิ่งสำคัญคือต้องจำไว้ว่าเมื่อสร้างวัตถุ ตัวสร้างของคลาสพื้นฐานจะถูกเรียกเป็นอันดับแรก หลังจากที่คอนสตรัคเตอร์นั้นเสร็จสิ้น โปรแกรมจะดำเนินการคอนสตรัคเตอร์ของคลาสที่สอดคล้องกับวัตถุที่เรากำลังสร้าง กล่าวอีกนัยหนึ่ง เมื่อสร้างCat
วัตถุตัวAnimal
สร้างจะทำงานก่อนและหลังจากนั้นคือ theCat
ตัวสร้างดำเนินการ หากต้องการดูสิ่งนี้ ให้เพิ่มเอาต์พุตของคอนโซลไปยังตัว สร้าง Cat
และAnimal
ตัวสร้าง
public class Animal {
public Animal() {
System.out.println("Animal constructor executed");
}
}
public class Cat extends Animal {
public Cat() {
System.out.println("Cat constructor executed!");
}
public static void main(String[] args) {
Cat cat = new Cat();
}
}
เอาต์พุตของคอนโซล: ตัวสร้างสัตว์ดำเนินการ ตัวสร้างแมวดำเนินการแล้ว! แน่นอนมันทำงานอย่างนั้น! ทำไม เหตุผลประการหนึ่งคือการหลีกเลี่ยงฟิลด์ที่ซ้ำกันที่ใช้ร่วมกันระหว่างสองคลาส ตัวอย่างเช่น สัตว์ทุกตัวมีหัวใจและสมอง แต่ไม่ใช่สัตว์ทุกตัวที่มีหาง เราสามารถประกาศ ฟิลด์ สมองและหัวใจซึ่งเป็นเรื่องปกติสำหรับสัตว์ทุกชนิดในAnimal
คลาสพ่อแม่ และ ฟิลด์ หางในCat
คลาสย่อย . ตอนนี้เราจะประกาศCat
ตัวสร้างคลาสที่รับอาร์กิวเมนต์สำหรับฟิลด์ทั้ง 3
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
จะไม่มีช่องสมองและหัวใจ ฟิลด์เหล่านี้ "สืบทอด" จากAnimal
คลาสพื้นฐาน คลาสที่สืบทอดสามารถเข้าถึงฟิลด์ของคลาสพื้นฐานดังนั้นจึงมองเห็นได้ในCat
คลาส ของเรา ด้วยเหตุนี้ เราจึงไม่จำเป็นต้องทำซ้ำฟิลด์เหล่านี้ในCat
ชั้นเรียน เราสามารถนำมาจากAnimal
ชั้นเรียน ยิ่งไปกว่านั้น เราสามารถเรียกตัวสร้างคลาสพื้นฐานในตัวสร้างคลาสลูกได้อย่างชัดเจน คลาสพื้นฐานเรียกอีกอย่างว่า " ซูเปอร์คลาส " นั่นเป็นเหตุผลที่ Java ใช้คำหลัก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
ตัวสร้างและผ่านสองช่อง เรามีฟิลด์เดียวที่จะเริ่มต้นอย่างชัดเจน: 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
โดยใช้สองคลาสนี้เป็นตัวอย่าง ตอนนี้เราจะดูกระบวนการสร้างอ็อบเจกต์และการเริ่มต้นตัวแปร เรารู้ว่ามีตัวแปรแบบสแตติกและอินสแตนซ์ (ไม่คงที่ ) เรารู้ด้วยว่าคลาสฐานมีตัวแปร และคลาสลูกก็มีตัวแปรของมันเอง เพื่อความชัดเจน เราจะเพิ่มตัวแปรสแตติกอย่างละหนึ่งตัวให้กับคลาสและคลาส ตัวแปร animalCount ในคลาสนี้จะแสดงจำนวนสายพันธุ์สัตว์ทั้งหมดบนโลกและcatCountAnimal
Cat
Animal
Cat
Animal
ตัวแปรจะหมายถึงจำนวนสายพันธุ์แมว นอกจากนี้ เราจะกำหนดค่าเริ่มต้นให้กับตัวแปรที่ไม่ใช่สแตติกทั้งหมดในทั้งสองคลาส (ซึ่งจะถูกเปลี่ยนในตัวสร้าง)
public class Animal {
String brain = "Initial value of brain in the Animal class";
String heart = "Initial value of heart in the Animal class";
public static int animalCount = 7700000;
public Animal(String brain, String heart) {
System.out.println("Animal base class constructor is running");
System.out.println("Have the variables of the Animal class already been initialized?");
System.out.println("Current value of static variable animalCount = " + animalCount);
System.out.println("Current value of brain in the Animal class = " + this.brain);
System.out.println("Current value of heart in the Animal class = " + this.heart);
System.out.println("Have the variables of the Cat class already been initialized?");
System.out.println("Current value of static variable catCount = " + Cat.catCount);
this.brain = brain;
this.heart = heart;
System.out.println("Animal base class constructor is done!");
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 = "Initial value of tail in the Cat class";
static int catCount = 37;
public Cat(String brain, String heart, String tail) {
super(brain, heart);
System.out.println("The cat class constructor has started (The Animal constructor already finished)");
System.out.println("Current value of static variable catCount = " + catCount);
System.out.println("Current value of tail = " + this.tail);
this.tail = tail;
System.out.println("Current value of tail = " + this.tail);
}
public static void main(String[] args) {
Cat cat = new Cat("Brain", "Heart", "Tail");
}
}
ดังนั้นเราจึงสร้างตัวอย่างใหม่ของCat
คลาสซึ่งสืบทอดAnimal
. เราได้เพิ่มเอาต์พุตคอนโซลแบบละเอียดเพื่อดูว่ามีอะไรเกิดขึ้นบ้างและเรียงลำดับอย่างไร นี่คือสิ่งที่จะแสดงเมื่อCat
สร้างวัตถุ: ตัวสร้างคลาส Animal base กำลังทำงาน มีการกำหนดค่าตัวแปรของคลาส Animal แล้วหรือยัง ค่าปัจจุบันของตัวแปรสแตติก animalCount = 7700000 ค่าปัจจุบันของสมองในคลาสสัตว์ = ค่าเริ่มต้นของสมองในคลาสสัตว์ ค่าปัจจุบันของหัวใจในคลาสสัตว์ = ค่าเริ่มต้นของหัวใจในคลาสสัตว์ มีตัวแปรของคลาสแมวอยู่แล้ว ได้รับการเริ่มต้น? ค่าปัจจุบันของตัวแปรสแตติก catCount = 37 ตัวสร้างคลาสฐานสัตว์เสร็จแล้ว! ค่าปัจจุบันของสมอง = สมอง ค่าปัจจุบันของหัวใจ = หัวใจ ตัวสร้างคลาส cat ได้เริ่มต้นขึ้น (ตัวสร้างสัตว์เสร็จสิ้นแล้ว) ค่าปัจจุบันของตัวแปรคงที่ catCount = 37 ค่าปัจจุบันของหาง = ค่าเริ่มต้นของหางในคลาส Cat ค่าปัจจุบันของหาง = หาง ตอนนี้เราสามารถเห็นลำดับของการกำหนดค่าเริ่มต้นตัวแปรและการเรียกใช้ตัวสร้างได้อย่างชัดเจนเมื่อสร้างวัตถุใหม่:
- ตัวแปรส แตติกของคลาสฐาน (
Animal
) จะถูกเตรียมใช้งาน ในกรณีของเราAnimalCountAnimal
ตัวแปรของคลาสถูกตั้งค่าเป็น 7700000 -
ตัวแปรส แตติกของคลาสลูก (
Cat
) จะถูกเตรียมใช้งานหมายเหตุ:เรายังคงอยู่ใน
Animal
ตัวสร้างและเราได้แสดงไว้แล้ว:ตัวสร้างคลาส Animal base กำลังทำงาน
มีการกำหนดค่าตัวแปรของคลาส Animal แล้วหรือยัง
ค่าปัจจุบันของตัวแปรสแตติก animalCount = 7700000
ค่าปัจจุบันของสมองในคลาสสัตว์ = ค่าเริ่มต้นของสมองในคลาสสัตว์ ค่าปัจจุบันของ
หัวใจในคลาสสัตว์ = ค่าเริ่มต้นของหัวใจในคลาสสัตว์
มีตัวแปรของคลาสแมวอยู่แล้ว ได้รับการเริ่มต้น?
ค่าปัจจุบันของตัวแปรคงที่ catCount = 37 -
จากนั้นตัวแปรที่ไม่คงที่ ของ คลาสฐานจะถูกเตรียมใช้งาน เราได้กำหนดค่าเริ่มต้นไว้โดยเฉพาะ ซึ่งจะถูกแทนที่ในตัวสร้าง ตัวสร้างสัตว์ยังไม่เสร็จ แต่ค่าเริ่มต้นของสมองและหัวใจถูกกำหนดไว้แล้ว:
ตัวสร้างคลาส Animal base กำลังทำงาน
มีการกำหนดค่าตัวแปรของคลาส Animal แล้วหรือยัง
ค่าปัจจุบันของตัวแปรคงที่ animalCount = 7700000
ค่าปัจจุบันของสมองในคลาสสัตว์ = ค่าเริ่มต้นของสมองในคลาสสัตว์
ค่าปัจจุบันของหัวใจในคลาสสัตว์ = ค่าเริ่มต้นของหัวใจในคลาสสัตว์ -
ตัวสร้างคลาสพื้นฐานเริ่มต้นขึ้น
เรามั่นใจตัวเองแล้วว่าขั้นตอนนี้เป็นขั้นตอนที่สี่: ในสามขั้นตอนแรกที่จุดเริ่มต้นของAnimal
คอนสตรัคเตอร์ ตัวแปรจำนวนมากได้ถูกกำหนดค่าไว้แล้ว -
ฟิลด์ที่ไม่คงที่ของคลาส ย่อย (
Cat
) จะถูกเตรียมใช้งาน
สิ่งนี้จะเกิดขึ้นก่อนที่Cat
ตัวสร้างจะเริ่มทำงาน
เมื่อเริ่มทำงาน ตัวแปรหางมีค่าอยู่แล้ว:ตัวสร้างคลาส cat เริ่มต้นแล้ว (ตัวสร้าง Animal เสร็จสิ้นแล้ว) ค่าปัจจุบันของตัวแปรคงที่ catCount = 37 ค่าปัจจุบันของหาง = ค่าเริ่มต้นของหางในคลาส Cat
-
คอนสตรัคเตอร์ของ
Cat
คลาสลูกเรียกว่าและนั่นคือลักษณะของการสร้างวัตถุใน Java!
ฉันต้องบอกว่าเราไม่ใช่แฟนตัวยงของการเรียนรู้แบบท่องจำ แต่เป็นการดีที่สุดที่จะจดจำลำดับของการเริ่มต้นตัวแปรและการเรียกใช้ตัวสร้าง
สิ่งนี้จะช่วยเพิ่มความเข้าใจของคุณเกี่ยวกับโฟลว์ของโปรแกรม และสถานะของออบเจกต์ของคุณในช่วงเวลาใดเวลาหนึ่ง
ยิ่งไปกว่านั้น คลาสจำนวนมากไม่ได้ใช้การสืบทอด ในกรณีนี้ จะไม่ใช้ขั้นตอนที่เกี่ยวข้องกับคลาสพื้นฐาน
อ่านเพิ่มเติม: |
---|
GO TO FULL VERSION