Menu
Coddy logo textTech

האופרטור 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 נפרדת.

challenge icon

אתגר

קל

בואו נבנה מערכת לבדיקת כלי רכב שמשתמשת באופרטור instanceof כדי לזהות בבטחה סוגים שונים של כלי רכב ולטפל בהם. תיצרו היררכיה של כלי רכב ותכתבו קוד שבודק את הסוג בפועל של כל כלי רכב לפני גישה לתכונות הייחודיות שלו.

תארגנו את הקוד שלכם בארבעה קבצים:

  • Vehicle.java: צרו מחלקת בסיס שמשותפת לכל כלי הרכב. לכל כלי רכב יש שדה model (String). הוסיפו בנאי כדי לאתחל אותו, מתודת getter בשם getModel(), ומתודה בשם inspect() שמדפיסה: Inspecting vehicle: [model]
  • Car.java: צרו מחלקה שיורשת מ-Vehicle. למכוניות יש שדה נוסף בשם numDoors (int). השתמשו ב-super לאתחול מחלקת האב. הוסיפו מתודה בשם checkDoors() שמדפיסה: [model] has [numDoors] doors
  • Motorcycle.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()
    }
}
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר Java אונליין