Menu
Coddy logo textTech

הרכבה מול ירושה

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

ירושה יוצרת קשר של "הוא-סוג-של": Dog הוא Animal. אבל מה אם מחלקה זקוקה לפונקציונליות של משהו שהיא אינה? כאן נכנסת לתמונה הרכבה, שיוצרת במקום זאת קשר של "יש-לו".

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

// גישת הירושה: Car הוא Engine (לא הגיוני)
class Car extends Engine { }

// גישת ההכלה: ל-Car יש Engine (הגיוני)
class Car {
    private Engine engine;
    
    public Car(Engine engine) {
        this.engine = engine;
    }
    
    public void start() {
        engine.ignite();
    }
}

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

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

הנחיה מעשית: השתמשו בירושה כשיש קשר אמיתי מסוג „הוא סוג של”, וכשהמחלקה היורשת אכן מייצגת גרסה מיוחדת של מחלקת האב.

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

challenge icon

אתגר

קל

בואו נבנה מערכת מחשב באמצעות הרכבה כדי להדגים את הקשר „יש לו”. במקום ש־Computer יירש את הרכיבים שלו (מה שלא היה הגיוני), המחשב שלך יכיל את החלקים הדרושים לו כדי לפעול.

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

  • Processor.java: צור מחלקה שמייצגת CPU. למחלקת Processor יש שני שדות פרטיים: brand (String) ו־speedGHz (double). כלול בנאי שמאתחל את שני השדות ומתודות getter עבור כל אחד מהם. הוסף מתודת process() שמחזירה String: [brand] processing at [speedGHz] GHz
  • Memory.java: צור מחלקה שמייצגת RAM. למחלקת Memory יש שני שדות פרטיים: type (String, כמו "DDR4" או "DDR5") ו־sizeGB (int). כלול בנאי, מתודות getter ומתודת load() שמחזירה: Loading [sizeGB]GB [type] memory
  • Computer.java: כאן ההרכבה באה לידי ביטוי! למחלקת Computer שלך צריכים להיות Processor ו־Memory כשדות פרטיים. היא לא מרחיבה אותם, אלא מכילה אותם. כלול בנאי שמקבל את שני הרכיבים. הוסף מתודת boot() שמחזירה String רב־שורות המציג את הפעלת המחשב באמצעות הרכיבים שלו:
    Booting computer...
    [processor.process() result]
    [memory.load() result]
    System ready!
    הוסף גם מתודת getSpecs() שמחזירה: Specs: [processor brand] CPU, [memory sizeGB]GB [memory type]
  • Main.java: הפח חיים במערכת שהרכבת! יתקבלו ארבעה קלטים: מותג המעבד (String), מהירות המעבד (double), סוג הזיכרון (String) וגודל הזיכרון (int).

    צור Processor ו־Memory עם הערכים האלה, ואז הרכב אותם לתוך Computer. הדפס את התוצאה של קריאה ל־boot(), ואז הדפס את התוצאה של getSpecs().

יתקבלו ארבעה קלטים לפי הסדר: מותג המעבד, מהירות המעבד (GHz), סוג הזיכרון וגודל הזיכרון (GB).

שים לב איך Computer מאצילה את העבודה לרכיבים שלה במקום לנסות להיות הם. זהו כוחה של ההרכבה! Computer יכולה להשתמש בכל Processor או Memory שתיתן לה, וכך העיצוב נעשה גמיש ומציאותי.

נסו בעצמכם

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // קרא את הקלטים
        String processorBrand = scanner.nextLine();
        double processorSpeed = Double.parseDouble(scanner.nextLine());
        String memoryType = scanner.nextLine();
        int memorySize = Integer.parseInt(scanner.nextLine());
        
        // TODO: צור Processor עם המותג והמהירות
        
        // TODO: צור Memory עם הסוג והגודל
        
        // TODO: צור Computer על ידי שילוב של Processor ו-Memory
        
        // TODO: הדפס את התוצאה של boot()
        
        // TODO: הדפס את התוצאה של getSpecs()
    }
}
quiz iconבחנו את עצמכם

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

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

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