יום טוב, איש ג'אווארש. התחלתי לקבל שאלות על ליהוק סוגי עזר ב-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