JavaRush /จาวาบล็อก /Random-TH /ตัวสร้างคลาสพื้นฐาน

ตัวสร้างคลาสพื้นฐาน

เผยแพร่ในกลุ่ม
สวัสดี! ครั้งสุดท้ายที่เราพูดคุยเกี่ยวกับตัวสร้างและเราได้เรียนรู้มากมายเกี่ยวกับพวกเขา ตอนนี้เราจะพูดถึงเรื่องเช่นตัวสร้างคลาสพื้นฐาน คลาสพื้นฐานคืออะไร? ความจริงก็คือใน Java คลาสที่แตกต่างกันหลายคลาสสามารถมีต้นกำเนิดร่วมกันได้ ตัวสร้างคลาสพื้นฐาน - 2สิ่งนี้เรียกว่ามรดก คลาสลูกหลานหลายคลาสสามารถมีคลาสบรรพบุรุษร่วมได้เพียงคลาสเดียว ตัวอย่างเช่น ลองจินตนาการว่าเรามีคลาส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!
แท้จริงแล้วมันทำงานอย่างไร! มีไว้เพื่ออะไร? ตัวอย่างเช่น เพื่อหลีกเลี่ยงไม่ให้ฟิลด์ทั่วไปของสองคลาสซ้ำกัน ตัวอย่างเช่น สัตว์ทุกตัวมีหัวใจและสมอง แต่ไม่ใช่สัตว์ทุกตัวที่มีหาง เราสามารถประกาศฟิลด์ที่เหมือนกันสำหรับสัตว์ทุกตัวbrainในheartคลาสแม่Animalและฟิลด์tailในคลาสCatย่อย ตอนนี้เราจะสร้าง Constructor สำหรับคลาส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จะไม่มีฟิลด์brainและheart. Animalฟิลด์เหล่านี้ถูก " ดึงขึ้นมา" จากคลาสพื้นฐาน คลาสลูกหลานสามารถเข้าถึงฟิลด์ของคลาสพื้นฐานได้ ดังนั้นจึงCatมองเห็นได้ในคลาสของเรา ดังนั้นเราจึงไม่จำเป็นCatต้องทำซ้ำฟิลด์เหล่านี้ในชั้นเรียน - เราสามารถนำมาจากชั้นเรียนAnimalได้ ยิ่งไปกว่านั้น เราสามารถเรียก Constructor ของคลาสพื้นฐานได้อย่างชัดเจนใน Constructor ของคลาสลูกหลาน คลาสพื้นฐานเรียกอีกอย่างว่า “ ซูเปอร์คลาสsuper ” ซึ่งเป็นสาเหตุที่ Java ใช้คีย์เวิร์ด ในตัวอย่างก่อนหน้านี้
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");
   }
}
ใน Constructor Catเราเรียก Constructor Animalและส่งผ่านสองฟิลด์ไปให้มัน เราจะต้องเริ่มต้นฟิลด์เดียวอย่างชัดเจนtailซึ่งAnimalไม่มีอยู่ จำได้ไหมที่เราบอกว่าเมื่อวัตถุถูกสร้างขึ้น Constructor ของคลาสพาเรนต์จะถูกเรียกก่อน? นี่คือเหตุผลว่าทำไมคำนี้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. ตอนนี้ เมื่อใช้ทั้งสองคลาสนี้เป็นตัวอย่าง เราจะดูกระบวนการสร้างอ็อบเจ็กต์และการเริ่มต้นตัวแปร เรารู้ว่าตัวแปรเป็นแบบคงที่และ ตัวแปรอินส แตนซ์ (ไม่คงที่) เรายังรู้ด้วยว่าคลาสพื้นฐานAnimalมีตัวแปรของตัวเอง และคลาสลูกหลานก็Catมีตัวแปรของตัวเอง มาเพิ่ม ตัวแปรคงที่หนึ่งตัวให้กับคลาสเพื่อAnimalความชัดเจน Catตัวแปร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 = Хвост
ตอนนี้เราสามารถเห็นได้อย่างชัดเจนว่าตัวแปรลำดับใดที่ถูกเตรียมใช้งานและตัวสร้างจะถูกเรียกเมื่อสร้างวัตถุใหม่:
  1. ตัวแปรคง ที่ ของคลาสพื้นฐาน ( ) จะถูกเตรียมใช้Animalงาน ในกรณีของเรา ตัวแปร animalCountคลาสAnimalถูกกำหนดให้เป็นค่า 7700000

  2. ตัวแปรคงที่ของคลาสลูกหลาน ( ) จะถูกเตรียมใช้Catงาน โปรดทราบ - เรายังอยู่ใน Constructor Animalและคอนโซลแจ้งว่า:

    
        Выполняется конструктор базового класса Animal
        Были ли уже проинициализированы переменные класса Animal?
        Текущее meaning статической переменной animalCount = 7700000
        Текущее meaning brain в классе Animal = Изначальное meaning brain в классе Animal
        Текущее meaning heart в классе Animal = Изначальное meaning heart в классе Animal
        Были ли уже проинициализированы переменные класса Cat?
        Текущее meaning статической переменной catsCount = 37
  3. ถัดไปตัวแปรที่ไม่คงที่ของคลาสฐาน จะถูกเตรียมใช้ งาน เราได้กำหนดค่าเริ่มต้นให้กับพวกเขาโดยเฉพาะ ซึ่งจะเปลี่ยนเป็นค่าใหม่ใน Constructor ตัวสร้างAnimalยังทำงานไม่เสร็จ แต่brainมีheartการกำหนดค่าเริ่มต้นแล้ว:

    
        Выполняется конструктор базового класса Animal
        Были ли уже проинициализированы переменные класса Animal?
        Текущее meaning статической переменной animalCount = 7700000
        Текущее meaning brain в классе Animal = Изначальное meaning brain в классе Animal
        Текущее meaning heart в классе Animal = Изначальное meaning heart в классе Animal
  4. ตัวสร้างคลาสพื้นฐานเริ่มทำงาน

    เราได้เห็นแล้วว่าขั้นตอนนี้เป็นเพียงขั้นตอนที่สี่: ในสามจุดแรก ในขณะที่ตัวสร้างเริ่มทำงานAnimalตัวแปรจำนวนมากได้ถูกกำหนดค่าไว้แล้ว

  5. การเริ่มต้นเขตข้อมูลที่ไม่คงที่ของคลาสลูก ( Cat)

    มันเกิดขึ้นก่อนที่นักออกแบบCatจะเริ่มทำงาน

    ในขณะที่เขาเริ่มทำงาน ตัวแปรtailมีค่าอยู่แล้ว:

    
    Конструктор класса Cat начал работу (конструктор Animal уже был выполнен)
    Текущее meaning статической переменной catsCount = 37
    Текущее meaning tail = Изначальное meaning tail в классе Cat
  6. ตัวสร้างของคลาสลูกหลานเรียกว่า Cat

นี่คือลักษณะของกระบวนการสร้างวัตถุใน Java! ฉันต้องบอกว่าเราไม่ใช่แฟนตัวยงของการยัดเยียด แต่ เป็นการดีกว่าที่จะจดจำลำดับของการเริ่มต้นตัวแปรและเรียกตัวสร้างและจดจำไว้ สำหรับอนาคต สิ่งนี้จะช่วยเพิ่มความเข้าใจของคุณเกี่ยวกับความคืบหน้าของโปรแกรมและสถานะของออบเจ็กต์ของคุณในช่วงเวลาใดก็ตาม นอกจากนี้ คลาสมักไม่มีคลาสพาเรนต์โดยตรง (คลาสซุปเปอร์/คลาสพื้นฐาน) ในกรณีนี้ รายการที่เกี่ยวข้องกับคลาสฐานจะไม่ถูกดำเนินการ
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION