Menu
Coddy logo textTech

מחלקות ומתודות מופשטות

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

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

מחלקה מופשטת מוכרזת באמצעות מילת המפתח abstract ואי אפשר ליצור ממנה מופע. היא יכולה להכיל גם מתודות רגילות עם מימוש וגם מתודות מופשטות שאין להן גוף:

public abstract class Shape {
    protected String color;
    
    public Shape(String color) {
        this.color = color;
    }
    
    // מתודה מופשטת - ללא מימוש
    public abstract double getArea();
    
    // מתודה רגילה - יש לה מימוש
    public String getColor() {
        return color;
    }
}

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

public class Circle extends Shape {
    private double radius;
    
    public Circle(String color, double radius) {
        super(color);
        this.radius = radius;
    }
    
    @Override
    public double getArea() {
        return Math.PI * radius * radius;
    }
}

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

Shape shape = new Circle("red", 5.0);
System.out.println(shape.getArea());  // קורא למימוש של Circle

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

challenge icon

אתגר

קל

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

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

  • Appliance.java: צרו מחלקה מופשטת שמשמשת כתבנית לכל מכשירי החשמל. לכל מכשיר חשמלי יש שדה brand (String) ושדה wattage (int). כללו בנאי שמאתחל את שני השדות, שיטות getter לכל אחד מהם, ושיטה רגילה getInfo() שמחזירה: [brand] - [wattage]W. הגדירו שיטה מופשטת operate() שמחלקות יורשות חייבות לממש — היא מייצגת את האופן שבו כל מכשיר חשמלי מבצע את הפעולה העיקרית שלו.
  • WashingMachine.java: צרו מחלקה קונקרטית שיורשת מ-Appliance. למכונות כביסה יש שדה נוסף capacity (int) שמייצג את גודל המטען בק״ג. השתמשו ב-super כדי לטפל באתחול של מחלקת האב. ממשו את השיטה operate() כך שתדפיס: [brand] washing machine is washing [capacity]kg of clothes
  • Microwave.java: צרו מחלקה קונקרטית נוספת שיורשת מ-Appliance. למיקרוגלים יש שדה power (int) שמייצג את אחוז עוצמת ההספק. ממשו את operate() כך שתדפיס: [brand] microwave is heating at [power]% power
  • Main.java: חברו את הכול יחד באמצעות פולימורפיזם. תקבלו חמש קלטים: שם מותג, הספק בוואטים, קיבולת מכונת הכביסה, שם מותג נוסף ורמת ההספק של המיקרוגל. צרו WashingMachine ו-Microwave, ואז אחסנו אותם במערך של הפניות מסוג Appliance. עברו בלולאה על המערך, ולכל מכשיר חשמלי הדפיסו את המידע שלו באמצעות getInfo() ולאחר מכן קראו ל-operate().

תקבלו חמישה קלטים בסדר הזה: מותג ראשון (String), הספק ראשון בוואטים (int), קיבולת בק״ג (int), מותג שני (String) ורמת הספק (int).

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

נסו בעצמכם

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // קראו את נתוני הקלט
        String brand1 = scanner.nextLine();
        int wattage1 = scanner.nextInt();
        int capacity = scanner.nextInt();
        scanner.nextLine(); // צרכו את תו ירידת השורה
        String brand2 = scanner.nextLine();
        int power = scanner.nextInt();
        
        // TODO: צרו אובייקט מסוג WashingMachine עם brand1, wattage1 ו-capacity
        
        // TODO: צרו אובייקט מסוג Microwave עם brand2, wattage1 (או הספק מתאים) ו-power
        
        // TODO: צרו מערך של הפניות מסוג Appliance ואחסנו בו את שני האובייקטים
        
        // TODO: עברו על המערך, ועבור כל מכשיר:
        // - הדפיסו את המידע עליו באמצעות getInfo()
        // - קראו ל-operate()
    }
}
quiz iconבחנו את עצמכם

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

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

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