האופרטור instanceof
חלק מהיחידה תכנות מונחה עצמים במסלול ה-Java של Coddy. שיעור 31 מתוך 87.
בשיעור הקודם ראית שהמרת טיפוס כלפי מטה עלולה להיכשל עם ClassCastException אם האובייקט אינו באמת מהטיפוס שאליו ממירים אותו. האופרטור instanceof פותר זאת בכך שהוא מאפשר לך לבדוק את הטיפוס של אובייקט לפני המרת הטיפוס.
התחביר פשוט: object instanceof ClassName מחזיר true אם האובייקט הוא מופע של המחלקה הזאת (או של כל אחת ממחלקות המשנה שלה):
Animal animal = new Dog();
if (animal instanceof Dog) {
Dog dog = (Dog) animal;
dog.bark(); // אפשר לקרוא בבטחה למתודות הייחודיות ל-Dog
}בדיקה זו מונעת שגיאות בזמן הריצה בכך שהיא מוודאת שההמרה תצליח. האופרטור מחזיר גם true עבור טיפוסי אב בהיררכיה:
Dog dog = new Dog();
System.out.println(dog instanceof Dog); // true
System.out.println(dog instanceof Animal); // true
System.out.println(dog instanceof Object); // trueמאז Java 16, אפשר לשלב את הבדיקה וההמרה בצעד אחד באמצעות התאמת תבניות:
if (animal instanceof Dog dog) {
dog.bark(); // 'dog' כבר הומר לסוג המתאים ומוכן לשימוש
}התחביר הנקי יותר הזה מבטל את הצורך בשורת המרה נפרדת. שימו לב ש־instanceof מחזירה false כשבודקים אותה מול null, ולכן אין צורך בבדיקת null נפרדת.
אתגר
קלבואו נבנה מערכת לבדיקת כלי רכב שמשתמשת באופרטור instanceof כדי לזהות בבטחה סוגים שונים של כלי רכב ולטפל בהם. תיצרו היררכיה של כלי רכב ותכתבו קוד שבודק את הסוג בפועל של כל כלי רכב לפני גישה לתכונות הייחודיות שלו.
תארגנו את הקוד שלכם בארבעה קבצים:
Vehicle.java: צרו מחלקת בסיס שמשותפת לכל כלי הרכב. לכל כלי רכב יש שדהmodel(String). הוסיפו בנאי כדי לאתחל אותו, מתודת getter בשםgetModel(), ומתודה בשםinspect()שמדפיסה:Inspecting vehicle: [model]Car.java: צרו מחלקה שיורשת מ-Vehicle. למכוניות יש שדה נוסף בשםnumDoors(int). השתמשו ב-superלאתחול מחלקת האב. הוסיפו מתודה בשםcheckDoors()שמדפיסה:[model] has [numDoors] doorsMotorcycle.java: צרו מחלקה נוספת שיורשת מ-Vehicle. לאופנועים יש שדה בשםhasSidecar(boolean). הוסיפו מתודה בשםcheckSidecar()שמדפיסה[model] has a sidecarאו[model] has no sidecar, בהתאם לערך הבוליאני.Main.java: כאןinstanceofנעשה חיוני! תקבלו ארבעה קלטים: דגם של מכונית, מספר הדלתות, דגם של אופנוע, והאם יש לו סירה צדדית (true/false).צרו מערך של הפניות מסוג
Vehicleשמכיל מכונית ואופנוע. לאחר מכן עברו בלולאה על המערך, ועבור כל כלי רכב:- קראו למתודת הבסיס
inspect() - השתמשו ב-
instanceofכדי לבדוק אם זה Car — אם כן, בצעו המרה בטוחה כלפי מטה וקראו ל-checkDoors() - השתמשו ב-
instanceofכדי לבדוק אם זה Motorcycle — אם כן, בצעו המרה בטוחה כלפי מטה וקראו ל-checkSidecar()
- קראו למתודת הבסיס
תקבלו ארבעה קלטים: דגם המכונית (String), מספר הדלתות (int), דגם האופנוע (String), והאם יש לו סירה צדדית (boolean).
הפלט שלכם צריך להציג ארבע שורות — עבור כל כלי רכב תופיע הודעת הבדיקה שלו ולאחריה הבדיקה הייחודית לסוג שלו. האופרטור instanceof מבטיח שתקראו למתודות של Car רק עבור מכוניות בפועל ולמתודות של Motorcycle רק עבור אופנועים בפועל, וכך מונע כל ClassCastException!
נסו בעצמכם
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// קראו את הקלטים
String carModel = scanner.nextLine();
int numDoors = Integer.parseInt(scanner.nextLine());
String motorcycleModel = scanner.nextLine();
boolean hasSidecar = Boolean.parseBoolean(scanner.nextLine());
// TODO: צרו אובייקט Car עם carModel ו־numDoors
// TODO: צרו אובייקט Motorcycle עם motorcycleModel ו־hasSidecar
// TODO: צרו מערך של הפניות ל־Vehicle המכיל את ה־Car וה־Motorcycle
// TODO: עברו על המערך, ועבור כל כלי רכב:
// 1. קראו למתודה inspect()
// 2. השתמשו ב־instanceof כדי לבדוק אם הוא Car, ואז בצעו המרת טיפוס כלפי מטה וקראו ל־checkDoors()
// 3. השתמשו ב־instanceof כדי לבדוק אם הוא Motorcycle, ואז בצעו המרת טיפוס כלפי מטה וקראו ל־checkSidecar()
}
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות התכנות מונחה העצמים
קבצים חיצונייםמבוא לתכנות מונחה עצמיםמחלקות לעומת אובייקטיםמילת המפתח thisמתודותשדות (מאפיינים)מתודת הבנאיהעמסת בנאיםחזרה – מחשבון פשוט4ירושה
ירושה בסיסית (extends)מילת המפתח superדריסת מתודות (@Override)שרשור בנאיםהמחלקה Objectירושה יחידה ורב־רמתיתלמה אין ירושה מרובה של מחלקותסיכום – היררכיית עובדים7מתודות מיוחדות ומחלקת Object
מתודת toString()equals() ו-hashCode()מתודת clone()compareTo() ו-Comparableהממשק Comparatorסיכום – מיון מותאם אישית2מצייני גישה ואנקפסולציה
סקירה של רמות הגישהמתודות Getter ו-Setterהסתרת מידעמילת המפתח finalסיכום – מנהל חשבון בנק5פולימורפיזם
יסודות העמסת מתודותדריסת מתודות (בזמן ריצה)המרה כלפי מעלה וכלפי מטההאופרטור instanceofמחלקות ומתודות מופשטותסיכום – מחשבון צורות8מושגי OOP מתקדמים
הרכבה מול ירושהאגרגציה מול הרכבהמחלקות פנימיות, מקוננות ואנונימיותEnums ומתודות של EnumRecords (Java 16+)מחלקות חתומות (Java 17+)3מאפייני מחלקה וחברים סטטיים
משתני מופע לעומת משתנים סטטייםמתודות סטטיותבלוקים סטטייםקבועים (static final)סיכום — מונה ומחלקת עזר6ממשקים ומחלקות מופשטות
מבוא לממשקיםמימוש ממשקיםמימוש של כמה ממשקיםמתודות ברירת מחדל וסטטיות בממשקמחלקות מופשטות לעומת ממשקיםממשקים פונקציונלייםסיכום – מערכת תשלומיםתרגלו בעצמכם: קומפיילר Java אונליין