Menu
Coddy logo textTech

מחלקות חתומות (Java 17+)

חלק מהיחידה תכנות מונחה עצמים במסלול ה-Java של Coddy. שיעור 52 מתוך 87.

ב-Java המסורתית, כשאתה יוצר מחלקה, כל מחלקה אחרת יכולה לרשת ממנה (אלא אם כן מסמנים אותה בתור final). אבל מה אם רוצים לאפשר ירושה, רק לא מכל אחד? Java 17 הציגה מחלקות אטומות כדי לתת לך שליטה מדויקת על אילו מחלקות יכולות לרשת מהמחלקה שלך.

מחלקה חתומה מצהירה במפורש על תת-המחלקות המורשות שלה באמצעות מילות המפתח sealed ו-permits:

sealed abstract class Shape permits Circle, Rectangle, Triangle {
    abstract double area();
}

final class Circle extends Shape {
    double radius;
    double area() { return Math.PI * radius * radius; }
}

final class Rectangle extends Shape {
    double width, height;
    double area() { return width * height; }
}

final class Triangle extends Shape {
    double base, height;
    double area() { return 0.5 * base * height; }
}

רק Circle,‏ Rectangle ו-Triangle יכולים לרשת את Shape. כל מחלקה אחרת שתנסה לרשת אותה תגרום לשגיאת הידור.

כל מחלקת משנה מותרת חייבת להשתמש באחד משלושה משני תכונות: final (לא ניתן להרחיב עוד), sealed (ממשיכה את שרשרת ההגבלות), או non-sealed (מאפשרת הרחבה ללא הגבלות):

sealed class Vehicle permits Car, Truck { }

final class Car extends Vehicle { }           // לא ניתן לרשת ממנה
non-sealed class Truck extends Vehicle { }    // כל אחד יכול לרשת מ־Truck

מחלקות אטומות עוצמתיות במיוחד בשילוב עם התאמת תבניות בביטויי switch, מכיוון שהמהדר מכיר את כל תתי־הסוגים האפשריים ויכול לוודא שהכיסוי מלא. הן אידיאליות למידול של קבוצה קבועה של סוגים בתחום מסוים, כמו אמצעי תשלום, סוגי תגובות או צורות גאומטריות.

challenge icon

אתגר

קל

בואו נבנה מערכת התראות שמדגימה מחלקות sealed באמצעות הגבלת סוגי ההתראות שיכולים להתקיים באפליקציה שלך. תיצור היררכיה שבה מותרים רק סוגי התראות מסוימים, וכל סוג מטפל בשליחה באופן שונה.

תארגן את הקוד שלך בחמישה קבצים:

  • Notification.java: צור מחלקה אבסטרקטית sealed שמשמשת כמחלקת הבסיס לכל ההתראות. היא צריכה להתיר בדיוק שלוש מחלקות משנה: EmailNotification, SMSNotification ו-PushNotification. המחלקה ה-sealed שלך צריכה לכלול שדה מוגן message (String), בנאי לאתחול שלו, getter להודעה ומתודה אבסטרקטית deliver() שמחזירה String המתאר כיצד ההתראה נשלחת.
  • EmailNotification.java: צור מחלקה final שיורשת מ-Notification. ל-EmailNotification יש שדה פרטי נוסף recipient (String) עבור כתובת האימייל. הבנאי שלה צריך לקבל גם את ההודעה וגם את הנמען, ולקרוא לבנאי של מחלקת האב באמצעות super(). המתודה deliver() צריכה להחזיר: Sending email to [recipient]: [message]
  • SMSNotification.java: צור מחלקה non-sealed שיורשת מ-Notification. כך מחלקות אחרות יוכלו לרשת ממנה אם יהיה בכך צורך בעתיד. ל-SMSNotification יש שדה פרטי נוסף phoneNumber (String). הבנאי שלה מקבל את ההודעה ואת מספר הטלפון. המתודה deliver() צריכה להחזיר: Sending SMS to [phoneNumber]: [message]
  • PushNotification.java: צור מחלקה final שיורשת מ-Notification. ל-PushNotification יש שדה פרטי נוסף deviceId (String). הבנאי שלה מקבל את ההודעה ואת מזהה המכשיר. המתודה deliver() צריכה להחזיר: Sending push to device [deviceId]: [message]
  • Main.java: חבר את מערכת ההתראות שלך! תקבל ארבעה קלטים: הודעה (String), כתובת אימייל (String), מספר טלפון (String) ומזהה מכשיר (String).

    צור התראה אחת מכל סוג, באמצעות אותה הודעה אך עם פרטי הקשר המתאימים לכל סוג. אחסן את שלושתן במערך מסוג Notification[] כדי להדגים פולימורפיזם עם מחלקות sealed. לאחר מכן עבור על המערך והדפס את התוצאה של קריאה ל-deliver() בכל התראה.

תקבל ארבעה קלטים לפי הסדר: הודעה, כתובת אימייל, מספר טלפון ומזהה מכשיר.

שים לב כיצד המחלקה sealed מגבילה את ההיררכיה: רק שלוש המחלקות המורשות יכולות לרשת מ-Notification. כל מחלקת משנה חייבת להצהיר שהיא final, sealed או non-sealed. כך תהיה לך שליטה מלאה בהיררכיית הטיפוסים שלך, תוך שמירה על האפשרות להשתמש בפולימורפיזם!

נסו בעצמכם

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // קראו את ארבעת ערכי הקלט
        String message = scanner.nextLine();
        String email = scanner.nextLine();
        String phoneNumber = scanner.nextLine();
        String deviceId = scanner.nextLine();
        
        // TODO: צרו מופע אחד מכל סוג התראה באמצעות אותה הודעה
        // - EmailNotification עם message ו-email
        // - SMSNotification עם message ו-phoneNumber
        // - PushNotification עם message ו-deviceId
        
        // TODO: אחסנו את כל שלוש ההתראות במערך Notification[]
        // כך מודגמת פולימורפיות באמצעות מחלקות חתומות
        
        // TODO: עברו על המערך והדפיסו את התוצאה של deliver()
        // עבור כל התראה
        
    }
}
quiz iconבחנו את עצמכם

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

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

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