Menu
Coddy logo textTech

מחלקות פנימיות, מקוננות ואנונימיות

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

ב-Java אפשר להגדיר מחלקות בתוך מחלקות אחרות. מחלקות פנימיות עוזרות לארגן את הקוד על ידי קיבוץ פונקציונליות קשורה, ויכולות לגשת ישירות לחברים של המחלקה החיצונית.

מחלקה פנימית מקוננת מוגדרת כחברה במחלקה אחרת. יש לה גישה לכל השדות והמתודות של המחלקה החיצונית, כולל הפרטיים:

class Outer {
    private String message = "Hello";
    
    class Inner {
        void display() {
            System.out.println(message);  // יכולה לגשת לשדה פרטי
        }
    }
}

// שימוש
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.display();  // מדפיסה: Hello

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

void process() {
    String prefix = "Result: ";
    
    class LocalHelper {
        void print(int value) {
            System.out.println(prefix + value);
        }
    }
    
    new LocalHelper().print(42);
}

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

Comparator<String> comp = new Comparator<String>() {
    @Override
    public int compare(String a, String b) {
        return a.length() - b.length();
    }
};

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

challenge icon

אתגר

קל

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

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

  • ShoppingCart.java: צרו את המחלקה החיצונית שמנהלת את חוויית הקנייה. ל- ShoppingCart שלכם צריך להיות שדה פרטי customerName (String).

    בתוך ShoppingCart, הגדירו מחלקה פנימית מקוננת בשם Item עם שני שדות פרטיים: name (String) ו-price (double). הוסיפו ל-Item בנאי שיאתחל את שני השדות ומתודה getDetails() שמחזירה: [name]: $[price]

    ל- ShoppingCart שלכם דרוש בנאי שמקבל את שם הלקוח, ומתודה בשם checkout() שמקבלת Item ואחוז הנחה (double). בתוך checkout():

    1. צרו מחלקה פנימית מקומית בשם DiscountCalculator עם מתודה applyDiscount(double originalPrice) שמחזירה את המחיר לאחר החלת אחוז ההנחה.
    2. השתמשו במחלקה המקומית כדי לחשב את המחיר הסופי.
    3. צרו מחלקה פנימית אנונימית שמממשת את הממשק Formatter (אתם תגדירו אותו) כדי לעצב את הקבלה. המחלקה האנונימית צריכה לדרוס מתודה format() שמחזירה מחרוזת קבלה מרובת שורות.

    המתודה checkout() צריכה להחזיר את מחרוזת הקבלה המעוצבת בפורמט המדויק הבא:

    --- Receipt ---
    Customer: [customerName]
    Item: [item details from getDetails()]
    Discount: [discount]%
    Final Price: $[calculated price]
  • Formatter.java: הגדירו ממשק פשוט עם מתודה יחידה: String format(). הממשק הזה ימומש על ידי המחלקה הפנימית האנונימית שלכם בתוך מתודת checkout.
  • Main.java: הפיחו חיים בעגלת הקניות שלכם! תקבלו שלוש קלטים: שם הלקוח (String), שם הפריט (String) ומחיר הפריט (double). אחוז ההנחה קבוע על 10.0.

    צרו ShoppingCart עם שם הלקוח. לאחר מכן צרו Item באמצעות תחביר ההפניה למחלקה החיצונית: cart.new Item(name, price). קראו ל-checkout() עם הפריט וההנחה, והדפיסו את הקבלה שהוחזרה.

תקבלו שלוש קלטים לפי הסדר: שם הלקוח, שם הפריט ומחיר הפריט.

לדוגמה, אם הקלטים הם Alice, Laptop ו-1000.0, המחיר הסופי לאחר הנחה של 10% יהיה 900.0.

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

נסו בעצמכם

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // קראו את הקלט
        String customerName = scanner.nextLine();
        String itemName = scanner.nextLine();
        double itemPrice = scanner.nextDouble();
        
        double discount = 10.0;
        
        // TODO: צרו ShoppingCart עם שם הלקוח
        
        // TODO: צרו Item באמצעות: cart.new Item(itemName, itemPrice)
        
        // TODO: קראו ל־checkout() עם הפריט וההנחה, ואז הדפיסו את התוצאה
        
    }
}
quiz iconבחנו את עצמכם

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

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

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