CodeGym /مدونة جافا /Random-AR /مثيل جافا للمشغل
John Squirrels
مستوى
San Francisco

مثيل جافا للمشغل

نشرت في المجموعة
أهلاً! سنتحدث اليوم عن مثيل عامل التشغيل، ونفكر في أمثلة لكيفية استخدامه، ونتطرق إلى بعض جوانب كيفية عمله:) لقد واجهت هذا العامل بالفعل في المستويات المبكرة من CodeGym. هل تتذكر لماذا نحتاجه؟ إذا لم يكن الأمر كذلك، فلا داعي للقلق. دعونا نتذكر معا. هناك حاجة إلى عامل تشغيل المثيل للتحقق مما إذا كان الكائن المشار إليه بواسطة متغير X قد تم إنشاؤه بناءً على فئة Y. هذا يبدو بسيطا. لماذا عدنا إلى هذا الموضوع؟ بادئ ذي بدء، لأنك الآن على دراية جيدة بآلية وراثة Java والمبادئ الأخرى لـ OOP. سيصبح الآن عامل التشغيل أكثر وضوحًا وسننظر في أمثلة أكثر تقدمًا حول كيفية استخدامه. دعنا نذهب! كيف يعمل مثيل المشغل - 1ربما تتذكر أن مثيل عامل التشغيل يُرجع صحيحًا إذا تم تقييم التحقق إلى صواب، أو خطأ إذا كان التعبير خطأ. وبناء على ذلك، فإنه عادة ما يحدث في جميع أنواع التعبيرات الشرطية ( if…else ). لنبدأ ببعض الأمثلة الأبسط:
public class Main {

   public static void main(String[] args) {

       Integer x = new Integer(22);

       System.out.println(x instanceof Integer);
   }
}
ما رأيك سيتم عرضه على وحدة التحكم؟ حسنًا، الأمر واضح هنا. :) الكائن x هو عدد صحيح، لذا ستكون النتيجة صحيحة . إخراج وحدة التحكم: صحيح فلنحاول التحقق مما إذا كانت سلسلة :
public class Main {

   public static void main(String[] args) {

       Integer x = new Integer(22);

       System.out.println(x instanceof String); // Error!
   }
}
لقد حصلنا على خطأ. وانتبه: أنشأ المترجم الخطأ قبل تشغيل الكود! ورأى على الفور أن العدد الصحيح والسلسلة لا يمكن تحويلهما تلقائيًا إلى بعضهما البعض ولا يرتبطان بالميراث. وبالتالي، لا يتم إنشاء كائن Integer استنادًا إلى String . يعد هذا أمرًا مريحًا ويساعد على تجنب أخطاء وقت التشغيل الغريبة، لذلك ساعدنا المترجم هنا :) الآن دعونا نحاول النظر في الأمثلة الأكثر صعوبة. بما أننا ذكرنا الميراث، فلنعمل مع نظام الفئات الصغير التالي:
public class Animal {

}

public class Cat extends Animal {

}

public class MaineCoon extends Cat {

}
نحن نعلم بالفعل كيف يتصرف المثيل عندما نتحقق مما إذا كان الكائن عبارة عن مثيلات لفئة، ولكن ماذا يحدث إذا أخذنا في الاعتبار العلاقة بين الوالدين والطفل؟ على سبيل المثال، في رأيك، ما الذي ستنتجه هذه التعبيرات:
public class Main {

   public static void main(String[] args) {

       Cat cat = new Cat();

       System.out.println(cat instanceof Animal);

       System.out.println(cat instanceof MaineCoon);

   }
}
الإخراج: صحيح خطأ السؤال الرئيسي الذي يجب الإجابة عليه هو بالضبط كيف يفسر مثيل "الكائن الذي تم إنشاؤه بناءً على فئة"؟ تم تقييم " مثيل القط للحيوان " على أنه صحيح ، ولكن بالتأكيد يمكننا العثور على خطأ في هذه الصياغة. لماذا يتم إنشاء كائن Cat بناءً على فئة الحيوان ؟ أليست مخلوقة على أساس فئتها وحدها؟ الجواب بسيط بما فيه الكفاية، وربما كنت قد فكرت في ذلك بالفعل. تذكر الترتيب الذي يتم به استدعاء المُنشئين وتهيئة المتغيرات عند إنشاء كائن. لقد تناولنا هذا الموضوع بالفعل في المقالة حول منشئي الفصل . وإليك مثال من هذا الدرس:
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");
   }
}
وإذا قمت بتشغيله في IDE، فستبدو مخرجات وحدة التحكم كما يلي: مُنشئ فئة الحيوان الأساسية قيد التشغيل هل تمت تهيئة متغيرات فئة الحيوان بالفعل؟ القيمة الحالية للمتغير الثابت AnimalCount = 7700000 القيمة الحالية للدماغ في فئة الحيوان = القيمة الأولية للدماغ في فئة الحيوان القيمة الحالية للقلب في فئة الحيوان = القيمة الأولية للقلب في فئة الحيوان هل لديك متغيرات فئة Cat بالفعل تمت التهيئة؟ القيمة الحالية للمتغير الثابت catCount = 37 تم الانتهاء من مُنشئ الفئة الأساسية للحيوان! القيمة الحالية للدماغ = الدماغ القيمة الحالية للقلب = القلب بدأ مُنشئ فئة القط (انتهى مُنشئ الحيوان بالفعل) القيمة الحالية للمتغير الثابت catCount = 37 القيمة الحالية للذيل = القيمة الأولية للذيل في فئة Cat القيمة الحالية للذيل = الذيل الآن هل تتذكر؟ :) يتم دائمًا استدعاء مُنشئ الفئة الأساسية، في حالة وجود فئة أساسية، أولاً عند إنشاء كائن. يسترشد عامل التشغيل بهذا المبدأ عند محاولة تحديد ما إذا كان الكائن A قد تم إنشاؤه بناءً على الفئة B. إذا تم استدعاء مُنشئ الفئة الأساسية، فلا يمكن أن يكون هناك شك. مع الفحص الثاني، كل شيء أسهل:
System.out.println(cat instanceof MaineCoon);
لم يتم استدعاء مُنشئ MaineCoon عند إنشاء كائن Cat، وهذا أمر منطقي . بعد كل شيء، MaineCoon هو سليل القط ، وليس سلفا. وهو ليس قالبًا لـ Cat . حسنًا، أعتقد أننا واضحون بشأن ذلك. ولكن ماذا سيحدث إذا فعلنا هذا؟:
public class Main {

   public static void main(String[] args) {

       Cat cat = new MaineCoon();

       System.out.println(cat instanceof Cat);
       System.out.println(cat instanceof MaineCoon);


   }
}
حسنًا... الآن أصبح الأمر أصعب. دعونا نتحدث عن ذلك. لدينا متغير Cat الذي قمنا بتخصيص كائن MaineCoon له. بالمناسبة، لماذا يعمل هذا حتى؟ يمكننا أن نفعل ذلك، أليس كذلك؟ نعم نستطيع. بعد كل شيء، كل MaineCoon هو قطة. إذا لم يكن ذلك واضحًا تمامًا، فتذكر مثال الأنواع البدائية المتوسعة:
public class Main {

   public static void main(String[] args) {

       long x = 1024;

   }
}
الرقم 1024 قصير : يمكن وضعه بسهولة في متغير طويل ، حيث أن هناك بايتات كافية لاستيعابه (هل تتذكر المثال مع الدمى؟) . يمكن دائمًا تعيين كائن سليل لمتغير سلف. في الوقت الحالي، فقط تذكر هذا، وفي الدروس اللاحقة سنقوم بتحليل كيفية عمله. إذن، ما الذي ينتجه مثالنا؟
Cat cat = new MaineCoon();
System.out.println(cat instanceof Cat);
System.out.println(cat instanceof MaineCoon);
ما سوف مثيل الاختيار؟ متغير Cat الخاص بنا أو كائن MaineCoon الخاص بنا؟ الجواب هو أن هذا السؤال بسيط بالفعل. تحتاج فقط إلى قراءة تعريف العامل مرة أخرى: هناك حاجة إلى عامل التشغيل للتحقق مما إذا كان الكائن المشار إليه بواسطة متغير X قد تم إنشاؤه بناءً على فئة Y. يقوم عامل التشغيل باختبار أصل الكائن، وليس نوع المتغير. وبالتالي، في هذا المثال، سيظهر برنامجنا صحيحًا في كلتا الحالتين: لدينا كائن MaineCoon . من الواضح أنه تم إنشاؤه بناءً على فئة MaineCoon ، ولكن تم إنشاؤه بناءً على فئة Cat الأصلية أيضًا!
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION