הרכבה לעומת הורשה
חלק מהיחידה תכנות מונחה עצמים במסלול ה-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(); // האצל את הפעולה ל-_engine
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..., לאחר מכן התוצאה של מתודת ה-process של ה-CPU, ולבסוף התוצאה של מתודת ה-load של ה-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 אונליין