Menu
Coddy logo textTech

מימוש לעומת הורשה

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

עכשיו, כשאתם מבינים גם את extends וגם את implements, בואו נבהיר מתי להשתמש בכל אחד מהם.

השתמשו ב־extends כשרוצים לרשת התנהגות. תת־המחלקה שלכם מקבלת את כל הקוד של מחלקת האב בחינם ויכולה להוסיף עליו:

class Animal {
  void breathe() {
    print('Breathing...');
  }
}

class Dog extends Animal {
  void bark() {
    print('Woof!');
  }
}

void main() {
  var dog = Dog();
  dog.breathe();  // עובר בירושה - פועל אוטומטית
  dog.bark();
}

השתמשו ב-implements כשרוצים להבטיח מבנה בלי לרשת קוד. עליכם לכתוב כל מתודה בעצמכם:

class Robot implements Animal {
  @override
  void breathe() {
    print('Ventilating circuits...');  // מימוש מותאם אישית לחלוטין
  }
}

ההבדל העיקרי: extends אומר „אני סוג של זה”, בעוד implements אומר „אני יכול לעשות את מה שזה עושה”. Dog הוא Animal ונושם באותה דרך. Robot אינו בעל חיים, אבל הוא יכול למלא את אותו חוזה באמצעות הלוגיקה שלו.

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

challenge icon

אתגר

קל

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

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

  • worker.dart: הגדירו כאן את היררכיית העובדים:
    • מחלקת Worker עם מאפיין String name ובנאי. כללו מתודה work() שמדפיסה [name] is working... ומתודה takeBreak() שמדפיסה [name] takes a coffee break
    • מחלקת OfficeWorker ש-extends את Worker. הוסיפו מאפיין String department. דרסו את work() כך שתדפיס [name] is typing reports in [department], אך השאירו את ההתנהגות של takeBreak() כפי שירש אותה
    • מחלקת RobotWorker ש-implements את Worker. הוסיפו מאפיין String model. מכיוון שרובוטים אינם באמת עובדים, אבל יכולים לעשות את מה שעובדים עושים, ספקו מימושים מותאמים אישית לחלוטין: work() אמורה להדפיס Robot [model] is assembling parts ו-takeBreak() אמורה להדפיס Robot [model] is recharging
  • main.dart: ייבאו את קובץ העובדים והדגימו את שתי הגישות:
    • צרו OfficeWorker בשם 'Alice' במחלקת 'Marketing'
    • צרו RobotWorker עם הדגם 'RX-7'
    • עבור עובד המשרד, קראו ל-work() ואז ל-takeBreak()
    • הדפיסו שורה ריקה
    • עבור העובד הרובוטי, קראו ל-work() ואז ל-takeBreak()

שימו לב איך OfficeWorker יורש את takeBreak() באופן אוטומטי מכיוון שהוא מרחיב את Worker — הוא באמת "הוא" עובד. לעומת זאת, RobotWorker חייב לספק מימוש משלו לכל דבר, מכיוון שהוא רק מממש את הממשק — הוא "יכול לעשות" את מה שעובד עושה, אבל בדרך רובוטית משלו.

הפלט הצפוי:

Alice is typing reports in Marketing
Alice takes a coffee break

Robot RX-7 is assembling parts
Robot RX-7 is recharging

נסו בעצמכם

import 'worker.dart';

void main() {
  // TODO: צור OfficeWorker בשם 'Alice' במחלקת 'Marketing'
  
  // TODO: צור RobotWorker מדגם 'RX-7'
  
  // TODO: עבור עובד המשרד, קרא ל־work() ולאחר מכן ל־takeBreak()
  
  // TODO: הדפס שורה ריקה
  
  // TODO: עבור העובד הרובוטי, קרא ל־work() ולאחר מכן ל־takeBreak()
}
quiz iconבחנו את עצמכם

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

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

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