CodeGym /مدونة جافا /Random-AR /بناة الطبقة الأساسية
John Squirrels
مستوى
San Francisco

بناة الطبقة الأساسية

نشرت في المجموعة
أهلاً! تحدثنا آخر مرة عن المُنشئين وتعلمنا الكثير عنهم. الآن سوف نتحدث عن منشئي الطبقة الأساسية .
منشئو الفئة الأساسية - 1
ما هي الطبقة الأساسية ؟ يتعلق الأمر بحقيقة أنه في Java يمكن أن يكون للعديد من الفئات المختلفة أصل مشترك.
منشئو الطبقة الأساسية - 2
وهذا ما يسمى الميراث . يمكن أن يكون لدى العديد من فئات الأطفال سلف مشترك واحد. على سبيل المثال، تخيل أن لدينا Animalفئة:
public class Animal {

   String name;
   int age;
}
يمكننا أن نعلن عن فئتين فرعيتين: Catو Dog. ويتم ذلك باستخدام الكلمة الأساسية يمتد .
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();
   }
}
إخراج وحدة التحكم: تم تنفيذ مُنشئ الحيوان تم تنفيذ مُنشئ Cat! في الواقع، إنه يعمل بهذه الطريقة! لماذا؟ أحد الأسباب هو تجنب تكرار الحقول المشتركة بين الفئتين. على سبيل المثال، كل حيوان لديه قلب وعقل، ولكن ليس كل حيوان لديه ذيل. يمكننا أن نعلن عن حقول الدماغ والقلب ، وهي مشتركة بين جميع الحيوانات، في الفئة الأم، وحقل الذيل في الفئة الفرعية. . سنعلن الآن عن مُنشئ فئة يأخذ الوسائط لجميع الحقول الثلاثة. AnimalCatCat
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. باستخدام هاتين الفئتين كأمثلة، سننظر الآن إلى عملية إنشاء كائن وتهيئة المتغيرات. نحن نعلم أن هناك متغيرات ثابتة ومتغيرات مثيلة (غير ثابتة) . نحن نعلم أيضًا أن Animalالفئة الأساسية لها متغيرات، والفئة Catالفرعية لها متغيرات خاصة بها. للتوضيح، سنضيف متغيرًا ثابتًا واحدًا لكل فئة Animalو 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إنشاء كائن: مُنشئ فئة الحيوان الأساسية قيد التشغيل هل تمت تهيئة متغيرات فئة الحيوان بالفعل؟ القيمة الحالية للمتغير الثابت AnimalCount = 7700000 القيمة الحالية للدماغ في فئة الحيوان = القيمة الأولية للدماغ في فئة الحيوان القيمة الحالية للقلب في فئة الحيوان = القيمة الأولية للقلب في فئة الحيوان هل لديك متغيرات فئة Cat بالفعل تمت التهيئة؟ القيمة الحالية للمتغير الثابت catCount = 37 تم الانتهاء من مُنشئ الفئة الأساسية للحيوان! القيمة الحالية للدماغ = الدماغ القيمة الحالية للقلب = القلب بدأ مُنشئ فئة القط (انتهى مُنشئ الحيوان بالفعل) القيمة الحالية للمتغير الثابت catCount = 37 القيمة الحالية للذيل = القيمة الأولية للذيل في فئة Cat القيمة الحالية للذيل = إذن ، يمكننا الآن أن نرى بوضوح ترتيب تهيئة المتغير واستدعاءات المنشئ عند إنشاء كائن جديد:
  1. تتم تهيئة المتغيرات الثابتة للفئة الأساسية ( ). Animalفي حالتنا، تم تعيين AnimalCountAnimal المتغير للفئة على 7700000.

  2. تتم تهيئة المتغيرات الثابتة للفئة الفرعية ( ).Cat

    ملاحظة: ما زلنا داخل Animalالمُنشئ وقد عرضنا بالفعل:

    مُنشئ فئة الحيوان الأساسية قيد التشغيل
    هل تمت تهيئة متغيرات فئة الحيوان بالفعل؟
    القيمة الحالية للمتغير الثابت AnimalCount = 7700000
    القيمة الحالية للدماغ في فئة الحيوان = القيمة الأولية للدماغ في فئة الحيوان
    القيمة الحالية للقلب في فئة الحيوان = القيمة الأولية للقلب في فئة الحيوان
    هل لديك متغيرات فئة Cat بالفعل تمت التهيئة؟
    القيمة الحالية للمتغير الثابت catCount = 37


  3. ثم تتم تهيئة المتغيرات غير الثابتة للفئة الأساسية . لقد قمنا بتعيين قيم أولية لهم على وجه التحديد، والتي يتم استبدالها بعد ذلك في المنشئ. لم ينته مُنشئ الحيوان بعد، ولكن تم بالفعل تعيين القيم الأولية للدماغ والقلب:

    مُنشئ فئة الحيوان الأساسية قيد التشغيل
    هل تمت تهيئة متغيرات فئة الحيوان بالفعل؟
    القيمة الحالية للمتغير الثابت AnimalCount = 7700000
    القيمة الحالية للدماغ في فئة الحيوان = القيمة الأولية للدماغ في فئة الحيوان
    القيمة الحالية للقلب في فئة الحيوان = القيمة الأولية للقلب في فئة الحيوان


  4. يبدأ مُنشئ الفئة الأساسية .
    لقد أقنعنا أنفسنا بالفعل أن هذه الخطوة هي الرابعة: في الخطوات الثلاث الأولى في بداية المنشئ Animal، تم بالفعل تعيين قيم للعديد من المتغيرات.


  5. تتم تهيئة الحقول غير الثابتة للفئة الفرعية ( ). يحدث هذا قبل بدء تشغيل المنشئ. عندما يبدأ التشغيل، يكون للمتغير tail قيمة بالفعل:Cat
    Cat

    بدأ مُنشئ فئة القط (انتهى مُنشئ الحيوان بالفعل) القيمة الحالية للمتغير الثابت catCount = 37 القيمة الحالية للذيل = القيمة الأولية للذيل في فئة Cat


  6. Catيتم استدعاء منشئ فئة الطفل

    وهذا ما يبدو عليه إنشاء كائن في Java!

    يجب أن أقول إننا لسنا من كبار المعجبين بالتعلم عن ظهر قلب، ولكن من الأفضل حفظ ترتيب التهيئة المتغيرة واستدعاءات المنشئ .

    سيؤدي هذا إلى زيادة فهمك لتدفق البرنامج بشكل كبير، وحالة الكائنات الخاصة بك في أي لحظة معينة.

    علاوة على ذلك، فإن العديد من الطبقات لا تستخدم الميراث. وفي هذه الحالة، لا تنطبق الخطوات المتعلقة بالفئة الأساسية.

المزيد من القراءة:

تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION