הרכבה לעומת הורשה
חלק מהיחידה תכנות מונחה עצמים במסלול ה-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();
}
}
}הנחיה נפוצה היא "העדיפו הרכבה על פני ירושה". השתמשו בירושה כשיש קשר אמיתי של "הוא-סוג-של" ואתם זקוקים לפולימורפיזם. השתמשו בהרכבה כשרוצים לעשות שימוש חוזר בהתנהגות בלי צימוד הדוק, או כשאובייקט זקוק ליכולות ממקורות מרובים.
אתגר
קלבואו נבנה מערכת מחשב באמצעות הרכבה! במקום לנסות לגרום למחשב לרשת מהחלקים שלו, תיצור מחלקות רכיבים נפרדות ותרכיב אותן יחד — כי למחשב יש 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.5GHz ועם16GB של זיכרון - קרא למתודת
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()
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות התכנות מונחה העצמים
קבצים חיצונייםספריות וייבואמבוא לתכנות מונחה עצמיםמחלקות לעומת אובייקטיםמילת המפתח thisמתודותמשתני מופעיסודות הבנאיחזרה: מחשבון פשוט4בטיחות מפני ערכי null
מבוא לבטיחות מפני ערכי nullניתן להקצאה ל-null לעומת לא ניתן להקצאה ל-nullהאופרטורים ? ו-!מילת המפתח Late ובטיחות מפני ערכי nullאופרטורים מודעי nullבטיחות מפני ערכי null במחלקותסיכום – מערכת פרופילי משתמשים7מחלקות מופשטות וממשקים
מחלקות מופשטותמתודות מופשטותממשקים ב-Dartממשקים משתמעיםמימוש לעומת הורשהממשקים מרוביםחזרה – מחשבון צורות10אוספים וגנריות
סקירה כללית של List, Set ו-Mapאוספים בטוחים מבחינת טיפוסיםמחלקות גנריותמתודות גנריותאילוצים גנרייםIterable ו-Iteratorסיכום – אחסון גנרי13מושגי OOP מתקדמים
הרכבה לעומת הורשהמתודות הרחבהמחלקות קריאותמחלקות אטומות (Dart 3)רשומות (Dart 3)תבניות והתאמה (3.0)טיפוסים מונים עם מתודות16פרויקט: ניהול ספרייה
סקירת הפרויקטמחלקות ספר ומשתמש2בנאים ב-Dart
בנאי ברירת מחדלבנאים בעלי שםרשימות אתחולבנאים קבועיםבנאי Factoryבנאים מפניםסיכום - בונה צורות5כימוס
חברים ציבוריים לעומת פרטייםמוסכמת הקידומת _פרטיות ברמת הספרייההעמקה ב-getters וב-settersהסתרת מידעסיכום – רשומות תלמידים8מיקסינים
מבוא למיקסיניםיצירת מיקסיניםשימוש במספר מיקסיניםמילת המפתח on במיקסיניםמיקסינים לעומת ירושהמיקסינים לעומת ממשקסיכום – מערכת בעלי החיים3מאפייני מחלקה
איברי מופע לעומת איברים סטטייםשדות final ו-constמשתני lateמתודות ושדות סטטייםGetters ו-Settersסיכום – מנהל חשבונות בנק6ירושה
ירושה בסיסיתמילת המפתח superדריסת מתודותהאנוטציה @overrideמילת המפתח final למחלקהבנאים וירושהסיכום – היררכיית עובדים9פולימורפיזם
יסודות הפולימורפיזםפולימורפיזם באמצעות ממשקיםבדיקת טיפוסים בזמן ריצההאופרטורים is ו-asמילת המפתח קווריאנטיסיכום — מעבד תשלומים12תכנות מונחה עצמים אסינכרוני
Future-ים ו-async/awaitיסודות ה-Streamsבקרי Streamsבנאים אסינכרונייםאסינכרוניות במתודות של מחלקהסיכום - אחזור נתוניםתרגלו בעצמכם: קומפיילר Dart אונליין