קומפוזיציה במקום ירושה
חלק מהיחידה תכנות מונחה עצמים במסלול ה-C# של Coddy. שיעור 41 מתוך 70.
ירושה יוצרת צימוד הדוק בין מחלקות. כש־Car יורשת מ־Vehicle, כל שינוי ב־Vehicle עלול לשבור את Car. הרכבה מציעה חלופה גמישה יותר: במקום לרשת התנהגות, מחלקה מכילה אובייקטים שמספקים את ההתנהגות הזאת.
חשבו על דמות במשחק שיכולה לנוע ולתקוף. באמצעות ירושה, ייתכן שתיצרו היררכיה מורכבת. באמצעות הרכבה, פשוט תתנו לדמות את הרכיבים שהיא צריכה:
public class MovementBehavior
{
public void Move() => Console.WriteLine("Moving...");
}
public class AttackBehavior
{
public void Attack() => Console.WriteLine("Attacking!");
}
public class Character
{
private MovementBehavior movement = new MovementBehavior();
private AttackBehavior attack = new AttackBehavior();
public void Move() => movement.Move();
public void Attack() => attack.Attack();
}ההבדל המרכזי הוא הקשר. ירושה מייצגת „הוא־סוג־של” (כלב הוא בעל חיים), ואילו הרכבה מייצגת „יש־לו” (לדמות יש התנהגות תנועה). הרכבה מאפשרת להחליף התנהגויות בזמן ריצה, לשלב יכולות בחופשיות ולהימנע מבעיית מחלקת הבסיס השברירית.
השתמשו בירושה כשיש קשר היררכי אמיתי. בחרו בהרכבה כשאתם זקוקים לגמישות, כשייתכן שהתנהגויות ישותפו בין מחלקות שאינן קשורות זו לזו, או כשאתם רוצים לשנות התנהגות באופן דינמי.
אתגר
קלבוא נבנה מערכת התראות שמדגימה את העוצמה של הרכבה לעומת הורשה. במקום ליצור היררכיה מורכבת של מחלקות התראות, תרכיבו NotificationSender על ידי מתן רכיבי התנהגות שניתן להחליף.
תארגנו את הקוד בשלושה קבצים:
Behaviors.cs: צרו שתי מחלקות התנהגות במרחב השמותNotifications, המטפלות בהיבטים שונים של שליחת התראות:FormattingBehavior- כוללת מתודהFormat(string message)שמחזירה את ההודעה כשהיא עטופה ב-[ALERT]בתחילתה וב-[END]בסופהDeliveryBehavior- כוללת מתודהDeliver(string channel, string message)שמחזירה מחרוזת בתבניתSending via {channel}: {message}
NotificationSender.cs: צרו מחלקהNotificationSenderבמרחב השמותNotifications, שמשתמשת בהרכבה כדי לשלב התנהגויות. על השולח:- להכיל מופעים של
FormattingBehaviorושלDeliveryBehaviorכשדות פרטיים - להכיל מאפיין
Channel(מחרוזת) ששומר את שם ערוץ המסירה - להכיל בנאי שמקבל את שם הערוץ
- להכיל מתודה
Send(string message)שמעצבת תחילה את ההודעה באמצעות התנהגות העיצוב, לאחר מכן מוסרת אותה באמצעות התנהגות המסירה ומחזירה את התוצאה הסופית
- להכיל מופעים של
Program.cs: בקובץ הראשי, צרוNotificationSenderעם ערוץ מהקלט, ולאחר מכן שלחו הודעה מהקלט. הדפיסו את התוצאה כדי להציג כיצד ההתנהגויות המשולבות פועלות יחד.
תקבלו שני קלטים:
- שם ערוץ המסירה (למשל,
Email,SMS) - ההודעה לשליחה
הדפיסו את התוצאה של קריאה ל-Send() על שולח ההתראות שלכם.
לדוגמה, אם הקלטים הם Email ו-Server is down, הפלט אמור להיות:
Sending via Email: [ALERT] Server is down [END]שימו לב ש-NotificationSender לא יורשת משום מחלקה — היא פשוט "מכילה" התנהגויות של עיצוב ומסירה. גישת ההרכבה הזו מאפשרת להחליף בקלות כל אחת מההתנהגויות בלי לשנות את מחלקת השולח, או לעשות שימוש חוזר בהתנהגויות האלה במחלקות שונות לחלוטין!
נסו בעצמכם
using System;
using Notifications;
class Program
{
public static void Main(string[] args)
{
// קראו את הקלט
string channel = Console.ReadLine();
string message = Console.ReadLine();
// TODO: צרו NotificationSender עם הערוץ
// TODO: שלחו את ההודעה והדפיסו את התוצאה
}
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות התכנות מונחה העצמים
קבצים חיצונייםמרחבי שמות והנחיותמבוא למחלקות ולאובייקטיםמילת המפתח 'this'מתודות ופרמטריםשדות לעומת מאפייניםבנאיםאתחול אובייקטיםסיכום – מחשבון פשוט4ירושה
תחביר ירושה בסיסית (:)מילת המפתח 'base'מילות המפתח Virtual ו-Overrideמחלקות Sealedמחלקת הבסיס 'object'סיכום – היררכיית עובדים7תכונות מתקדמות
העמסת אופרטוריםאינדקסרים (this[])דריסת ToString()מתודות הרחבהסיכום – רשימה מותאמת אישית2מאפיינים וחברים סטטיים
מאפיינים במימוש אוטומטימאפיינים לקריאה בלבד ולכתיבה בלבדשדות ומתודות סטטייםמחלקות סטטיותחברים עם גוף ביטוי5פולימורפיזם וממשקים
פולימורפיזם בזמן קומפילציה לעומת בזמן ריצהממשק לעומת מחלקה מופשטתממשקים מרוביםממשקים מפורשיםהמרה כלפי מעלה והמרה כלפי מטהחזרה: מחשבון צורות8מושגים מתקדמים בתכנות מונחה עצמים
קומפוזיציה במקום ירושהGenerics (מחלקות ומתודות)נציגים ואירועיםמאפיינים ורפלקציהIDisposable והצהרת usingיסודות הזרקת תלויותתרגלו בעצמכם: קומפיילר C# אונליין