JavaRush /وبلاگ جاوا /Random-FA /سازندگان کلاس پایه

سازندگان کلاس پایه

در گروه منتشر شد
سلام! آخرین بار در مورد سازنده ها صحبت کردیم و چیزهای زیادی در مورد آنها یاد گرفتیم. اکنون در مورد چیزی به عنوان سازنده کلاس پایه صحبت خواهیم کرد. کلاس پایه چیست ؟ واقعیت این است که در جاوا، چندین کلاس مختلف می توانند منشا مشترکی داشته باشند. سازندگان کلاس پایه - 2به این می گویند وراثت . چندین کلاس از نسل می توانند یک کلاس اجداد مشترک داشته باشند. به عنوان مثال، تصور کنید که ما یک کلاس Animal(حیوان) داریم:
public class Animal {

   String name;
   int age;
}
ما می توانیم برای آن، به عنوان مثال، 2 کلاس descendant ایجاد کنیم - 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. اکنون یک سازنده برای کلاس ایجاد می کنیم 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. کلاس descendant به فیلدهای کلاس پایه دسترسی دارد، بنابراین Catآنها در کلاس ما قابل مشاهده هستند. Catبنابراین، ما نیازی به کپی کردن این فیلدها در کلاس نداریم - می توانیم آنها را از کلاس بگیریم Animal. علاوه بر این، می‌توانیم به صراحت سازنده کلاس پایه را در سازنده کلاس decendant فراخوانی کنیم. کلاس پایه نیز " superclass " نامیده می شود، به همین دلیل جاوا از کلمه کلیدی استفاده می کند 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");
   }
}
کامپایلر می داند که هنگام ایجاد یک شی از یک کلاس نزول، سازنده کلاس پایه ابتدا فراخوانی می شود. و اگر سعی کنید به صورت دستی این رفتار را تغییر دهید، اجازه نمی دهد.

فرآیند ایجاد یک شی.

در بالا به مثالی با کلاس پایه و والد نگاه کردیم - Animaland Cat. اکنون با استفاده از این دو کلاس به عنوان مثال، به روند ایجاد یک شی و مقداردهی اولیه متغیرها خواهیم پرداخت. می دانیم که متغیرها ثابت و متغیرهای نمونه (غیر ایستا) هستند. همچنین می دانیم که کلاس پایه Animalمتغیرهای خاص خود را دارد و کلاس decendant نیز متغیرهای 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. توجه کنید - ما هنوز داخل سازنده هستیم Animalو کنسول قبلاً می گوید:

    
        Выполняется конструктор базового класса Animal
        Были ли уже проинициализированы переменные класса Animal?
        Текущее meaning статической переменной animalCount = 7700000
        Текущее meaning brain в классе Animal = Изначальное meaning brain в классе Animal
        Текущее meaning heart в классе Animal = Изначальное meaning heart в классе Animal
        Были ли уже проинициализированы переменные класса Cat?
        Текущее meaning статической переменной catsCount = 37
  3. سپس، متغیرهای غیراستاتیک کلاس پایه مقداردهی اولیه می شوند . ما به طور خاص مقادیر اولیه را به آنها اختصاص دادیم، که سپس به مقادیر جدید در سازنده تغییر می کنند. سازنده 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. سازنده کلاس decendant نامیده می شود Cat

روند ایجاد یک شی در جاوا به این صورت است! باید بگویم که ما طرفدار زیادی از cramming نیستیم، اما بهتر است ترتیب مقداردهی اولیه متغیرها و فراخوانی سازنده ها را به خاطر بسپاریم و آنها را برای آینده به خاطر بسپاریم . این به میزان زیادی درک شما را از پیشرفت برنامه و وضعیت اشیاء در هر لحظه افزایش می دهد. علاوه بر این، کلاس‌ها اغلب کلاس‌های والد مستقیم (کلاس‌های سوپرکلاس/کلاس‌های پایه) ندارند. در این صورت آیتم های مرتبط با کلاس پایه اجرا نمی شوند.
نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION