CodeGym /وبلاگ جاوا /Random-FA /سازندگان کلاس پایه
John Squirrels
مرحله
San Francisco

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

در گروه منتشر شد
سلام! آخرین بار در مورد سازندگان صحبت کردیم و چیزهای زیادی در مورد آنها یاد گرفتیم. اکنون می خواهیم در مورد سازنده های کلاس پایه صحبت کنیم .
سازندگان کلاس پایه - 1
کلاس پایه چیست ؟ این به این واقعیت مربوط می شود که در جاوا چندین کلاس مختلف می توانند منشا مشترکی داشته باشند.
سازندگان کلاس پایه - 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 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 constructor اجرا شد Cat constructor اجرا شد! در واقع، این روش کار می کند! چرا؟ یکی از دلایل این است که از تکرار فیلدهای مشترک بین دو کلاس خودداری کنید. مثلاً هر حیوانی قلب و مغز دارد اما هر حیوانی دم ندارد. می‌توانیم میدان‌های مغز و قلب را که برای همه حیوانات مشترک هستند، در 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. کلاس inheriting به فیلدهای کلاس پایه دسترسی دارد ، بنابراین آنها در Catکلاس ما قابل مشاهده هستند. در نتیجه نیازی نیست که این فیلدها را در Catکلاس کپی کنیم. می توانیم آنها را از کلاس ببریم Animal. علاوه بر این، ما می توانیم به صراحت سازنده کلاس پایه را در سازنده کلاس فرزند صدا کنیم. به یک کلاس پایه " 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کلاس پایه دارای متغیرهایی است و Catکلاس فرزند متغیرهای خود را دارد. Animalبرای وضوح، هر کدام یک متغیر استاتیک به کلاس‌های and اضافه می‌کنیم Cat. متغیر animalCount در کلاس تعداد کل گونه های جانوری روی زمین را نشان می دهد و متغیر catCount تعداد گونه های گربه را نشان می دهد . علاوه بر این، مقادیر شروع را به همه متغیرهای غیر استاتیک در هر دو کلاس اختصاص می‌دهیم (که سپس در سازنده تغییر خواهند کرد). 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 قبلاً مقداردهی اولیه شده اند؟ مقدار فعلی متغیر استاتیک animalCount = 7700000 مقدار فعلی مغز در کلاس Animal = مقدار اولیه مغز در کلاس Animal مقدار فعلی قلب در کلاس Animal = مقدار اولیه قلب در کلاس Animal متغیرهای کلاس Cat قبلاً اولیه شده است؟ مقدار فعلی متغیر استاتیک catCount = 37 سازنده کلاس Animal base تمام شد! مقدار کنونی مغز = مغز مقدار فعلی قلب = قلب سازنده کلاس cat شروع شده است (سازنده Animal قبلاً تمام شده است) مقدار فعلی متغیر ثابت catCount = 37 مقدار فعلی دم = مقدار اولیه دم در کلاس Cat مقدار فعلی دم = Tail بنابراین، اکنون می توانیم ترتیب اولیه سازی متغیر و فراخوانی سازنده را هنگام ایجاد یک شی جدید به وضوح ببینیم:
  1. متغیرهای استاتیک از کلاس پایه ( Animal) مقداردهی اولیه می شوند. در مورد ما، متغیر animalCountAnimal کلاس روی 7700000 تنظیم شده است.

  2. متغیرهای استاتیک کلاس فرزند ( Cat) مقداردهی اولیه می شوند.

    توجه: ما هنوز داخل سازنده هستیم Animalو قبلاً نمایش داده ایم:

    سازنده کلاس Animal در حال اجرا است
    آیا متغیرهای کلاس Animal قبلاً مقداردهی اولیه شده اند؟
    مقدار فعلی متغیر استاتیک animalCount = 7700000
    مقدار فعلی مغز در کلاس Animal = مقدار اولیه مغز در کلاس Animal
    مقدار فعلی قلب در کلاس Animal = مقدار اولیه قلب در کلاس Animal
    متغیرهای کلاس Cat قبلاً اولیه شده است؟
    مقدار فعلی متغیر استاتیک catCount = 37


  3. سپس متغیرهای غیر استاتیک کلاس پایه مقدار دهی اولیه می شوند. ما به طور خاص مقادیر اولیه را به آنها اختصاص دادیم، که سپس در سازنده جایگزین می شوند. سازنده Animal هنوز تمام نشده است، اما مقادیر اولیه مغز و قلب قبلاً تعیین شده است:

    سازنده کلاس Animal در حال اجرا است
    آیا متغیرهای کلاس Animal قبلاً مقداردهی اولیه شده اند؟
    مقدار فعلی متغیر استاتیک animalCount = 7700000
    مقدار فعلی مغز در کلاس Animal = مقدار اولیه مغز در کلاس Animal
    مقدار فعلی قلب در کلاس Animal = مقدار اولیه قلب در کلاس Animal


  4. سازنده کلاس پایه شروع می شود.
    ما قبلاً خودمان را متقاعد کرده ایم که این مرحله چهارم است: در سه مرحله اول در ابتدای سازنده Animal، به بسیاری از متغیرها قبلاً مقادیر اختصاص داده شده است.


  5. فیلدهای غیر استاتیک کلاس فرزند ( Cat) مقدار دهی اولیه می شوند.
    این قبل از Catشروع اجرا شدن سازنده اتفاق می افتد.
    هنگامی که شروع به اجرا می کند، متغیر tail از قبل دارای یک مقدار است:

    سازنده کلاس cat شروع شده است (سازنده Animal قبلاً تمام شده است) مقدار فعلی متغیر استاتیک catCount = 37 مقدار فعلی دم = مقدار اولیه دم در کلاس Cat


  6. سازنده Catکلاس فرزند فراخوانی می شود

    و این چیزی است که ایجاد یک شی در جاوا به نظر می رسد!

    باید بگویم که ما طرفدار زیادی از یادگیری روت نیستیم، اما بهتر است ترتیب اولیه سازی متغیرها و فراخوانی های سازنده را به خاطر بسپاریم .

    این امر درک شما را از جریان برنامه و وضعیت اشیاء شما در هر لحظه خاص بسیار افزایش می دهد.

    علاوه بر این، بسیاری از کلاس ها از وراثت استفاده نمی کنند. در این مورد، مراحل مربوط به کلاس پایه اعمال نمی شود.

نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION