Menu
CoddyTech

הרכבה לעומת הורשה

חלק מהיחידה תכנות מונחה עצמים במסלול ה-Dart של Coddy. שיעור 82 מתוך 110.

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

נבחן מחלקה Car. באמצעות ירושה, אולי תנסה להרחיב מחלקה Engine — אבל מכונית אינה מנוע, יש לה מנוע:

class Engine {
  void start() => print('Engine started');
}

class Car {
  final Engine _engine = Engine();  // קומפוזיציה: ל-Car יש Engine
  
  void start() {
    _engine.start();  // האצל למנוע
    print('Car is ready to drive');
  }
}

void main() {
  var car = Car();
  car.start();
}

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

class ElectricEngine {
  void start() => print('Electric motor humming');
}

class HybridCar {
  Engine? _gasEngine;
  ElectricEngine? _electricEngine;
  
  HybridCar({bool useElectric = false}) {
    if (useElectric) {
      _electricEngine = ElectricEngine();
    } else {
      _gasEngine = Engine();
    }
  }
}

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

challenge icon

אתגר

קל

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

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

  • components.dart: צור שתי מחלקות רכיבים שמייצגות חלקי מחשב:
    • מחלקת CPU עם String brand ו-double speedGHz. כלול בה מתודת process() שמחזירה מחרוזת: [brand] processing at [speedGHz]GHz
    • מחלקת Memory עם int sizeGB. כלול בה מתודת load() שמחזירה מחרוזת: Loading [sizeGB]GB of data
  • computer.dart: צור מחלקת Computer שמשתמשת בהרכבה כדי לשלב את הרכיבים. המחשב שלך צריך:
    • שדה String name
    • להכיל מופעים של CPU ושל Memory (הרכבה — למחשב יש את החלקים האלה)
    • לקבל את כל הערכים הדרושים דרך הבנאי שלו, כדי ליצור את שני הרכיבים בתוכו
    • שתהיה לו מתודת boot() שמעבירה את העבודה לשני הרכיבים ומדפיסה שלוש שורות: שם המחשב ואחריו starting..., אחר כך את התוצאה של מתודת העיבוד של ה-CPU, ואז את התוצאה של מתודת הטעינה של ה-Memory
    • שתהיה לו מתודת specs() שמחזירה מחרוזת שמתארת את המערכת: [name]: [brand] [speedGHz]GHz, [sizeGB]GB RAM
  • main.dart: יבא את הקבצים שלך והדגם הרכבה בפעולה:
    • צור Computer בשם Workstation עם CPU של Intel שפועל במהירות 3.5 GHz ועם 16 GB של זיכרון
    • קרא למתודת boot()
    • הדפס את התוצאה של specs()

שים לב שמחלקת Computer לא יורשת מ-CPU או מ-Memory — היא מכילה אותם ומעבירה אליהם את העבודה. זהו קשר "יש לו" שנוצר באמצעות הרכבה!

הפלט הצפוי:

Workstation starting...
Intel processing at 3.5GHz
Loading 16GB of data
Workstation: Intel 3.5GHz, 16GB RAM

נסו בעצמכם

import 'computer.dart';

void main() {
  // TODO: צרו Computer בשם "Workstation" עם:
  // - מעבד Intel הפועל בתדר 3.5 GHz
  // - זיכרון בנפח 16 GB

  // TODO: קראו למתודה boot()

  // TODO: הדפיסו את התוצאה של specs()
}
quiz iconבחנו את עצמכם

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

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

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