يوم جيد، يا رجل جافاراش. بدأت في تلقي أسئلة حول إرسال الأنواع المرجعية في Java. لكي لا أعيد سرد نفس الشيء في كل مرة، قررت أن أكتب مقالًا قصيرًا.
أولاً، دعونا نلقي نظرة على نوع الصب.
تحويل النوع (تحويل النوع) هو تحويل قيمة متغيرة من نوع ما إلى قيمة من نوع آخر. دعونا نلقي نظرة على مثال لما هو عليه وما يؤكل به. لدينا بعض التسلسل الهرمي للفئات ( انظر الشكل 1 ). هنا يمكنك رؤية جميع فئات التسلسل الهرمي، ومن يرث من، وطرق كل فئة. هناك تقريب التوسع والتعاقد. ونحن نرى أن الطبقةCat
هي سليل الطبقة Pet
. Pet
، بدوره، هو خليفة الطبقة Animal
. عندما نكتب:
Animal animalCat = new Cat();
Animal animalDog = new YorkshireTerrier();
هذا فريق عمل متوسع (أو ضمني). لقد قمنا بتوسيع الروابط animalCat
و animalDog
. يشيرون إلى الأشياء Cat
و Dog
. مع مثل هذا التمثيل، لا يمكننا animalCat/animalDog
استدعاء الأساليب من خلال مرجع موجود في Cat/Dog
، ولكنه ليس موجودًا في Animal
. يحدث تضييق (أو صريح) في الاتجاه المعاكس:
Animal animalCat = new Cat();
Animal animalDog = new YorkshireTerrier();
Cat cat =(Cat)animalCat;
YorkshireTerrier dog = (YorkshireTerrier) animalDog;
لقد أوضحنا بوضوح النوع الذي نريد أن نلقي عليه هذا الكائن. لكن كن حذرا!!! إذا كنت تفعل ذلك مثل هذا:
Animal animalCat = new Cat();
YorkshireTerrier dog = (YorkshireTerrier) animalCat;
سيقوم المترجم بتخطي هذا الرمز. لكنه RunTime
سيطردك:
Exception in thread "main" java.lang.ClassCastException: Animals.Cat cannot be cast to Animals.YorkshireTerrier
RunTime
يرى أن Cat
هناك YorkshireTerrier
فئتين مختلفتين. لتجنب ClassCastException أثناء تضييق التحويل، استخدم instanceof
.
Animal animalCat = new Cat();
if (animalCat instanceof YorkshireTerrier)
{
YorkshireTerrier dog = (YorkshireTerrier) animalCat;
}
إذا animalCat
كان الأمر كذلك YorkshireTerrier
، فسيتم التعيين، وإذا لم يكن الأمر كذلك، فلن يحدث شيء.
الآن لماذا يعد هذا ضروريًا إذا فقدنا الأساليب وتمكنا من الحصول على مثل هذه الأخطاء
دعونا نلقي نظرة على الكود الذي قمت بإنشائه وفقًا للرسم التخطيطي في الشكل. 1 . فصلAnimal
public abstract class Animal
{
String name;
int age;
String nameOfClass = getClass().getSimpleName();
public void eat(){
System.out.println(nameOfClass + ": Omnomnom");
}
public void sleep(){
System.out.println(nameOfClass + ": Z-z-z-z");
}
}
الطبقة WildAnimal
التي ترث منAnimal
public abstract class WildAnimal extends Animal
{
public void steelChicken()
{
System.out.println(nameOfClass+": Muhaha,I stole a chicken!");
}
}
الطبقة Pet
التي ترث منAnimal
public abstract class Pet extends Animal
{
public void peeInTray(){
System.out.println(nameOfClass + ": Master, I peed");
}
}
الطبقة Fox
التي ترث منWildAnimal
public class Fox extends WildAnimal
{
public void eatColobok(){
System.out.println(nameOfClass + ": I will eat you, Colobok");
}
}
الطبقة Wolf
التي ترث منWildAnimal
public class Wolf extends WildAnimal
{
public void hawlAtTheMoon(){
System.out.println(nameOfClass + ": Ouuuuu!!!Ouuuu!!!");
}
}
الطبقة Cat
التي ترث منPet
public class Cat extends Pet
{
public void sleepOnKeyboard(){
System.out.println(nameOfClass + ": Master, stop working!!I wanna sleep on your keyboard");
}
}
الطبقة YorkshireTerrier
التي ترث منPet
public class YorkshireTerrier extends Pet
{
public void bark(){
System.out.println(nameOfClass + ": Meow!!! Meow!!!");
}
}
تخيل الوضع. نحن بحاجة إلى جمع كل الحيوانات في قائمة واحدة، وإطعامهم ثم وضعهم في السرير. من السهل القيام بذلك إذا خلقنا ArrayList
حيوانات ( Animal
). ومن ثم نطلق على الطرق المقابلة لكل حيوان ما يلي:
public class ZOO
{
public static void main(String[] args)
{
List<Animal> allAnimals = new ArrayList<>();
allAnimals.add(new Cat());
allAnimals.add(new Wolf());
allAnimals.add(new Fox());
allAnimals.add(new YorkshireTerrier());
for (Animal animal : allAnimals)
{
animal.eat();
animal.sleep();
}
}
}
لا يمكنني animal
استدعاء الطريقة bark()
أو sleepOnKeyboard()
. لأن الورقة allAnimals
تحتوي على قطة وذئب ويوريك وثعلب، لكنها مختزلة إلى Animal
. وليس لديهم سوى الأساليب الموجودة في Animal
. هذا جيد جدًا، لأنه إذا كان بإمكاننا استدعاء جميع الطرق، فلماذا نحتاج إلى ذئب ينام على لوحة المفاتيح، أو يوريك يسرق الدجاج؟ شكرًا لكم على اهتمامكم. آمل أن تكون هذه المقالة مفيدة لك. النقد والتعليقات موضع ترحيب)
GO TO FULL VERSION