מילות המפתח Virtual ו-Override
חלק מהיחידה תכנות מונחה עצמים במסלול ה-C# של Coddy. שיעור 21 מתוך 70.
כאשר מחלקה נגזרת יורשת מתודה, לפעמים רוצים לשנות לחלוטין את אופן הפעולה של המתודה. מילות המפתח virtual ו-override פועלות יחד כדי לאפשר זאת באופן מבוקר.
סמנו מתודה בתור virtual במחלקת הבסיס כדי לציין שמחלקות יורשות רשאיות להחליף את המימוש שלה:
public class Animal
{
public virtual void Speak()
{
Console.WriteLine("Some sound");
}
}
public class Dog : Animal
{
public override void Speak()
{
Console.WriteLine("Woof!");
}
}מילת המפתח override במחלקה הנגזרת אומרת למהדר שאתה מחליף בכוונה את המתודה של מחלקת הבסיס. בלי virtual במתודה של מחלקת הבסיס, אי אפשר להשתמש ב־override.
הכוח האמיתי מתגלה כשמשתמשים בהפניה למחלקת בסיס כדי להחזיק אובייקט ממחלקה נגזרת:
Animal myPet = new Dog();
myPet.Speak(); // פלט: Woof!אף על פי ש-myPet מוצהר כ-Animal, C# קוראת לגרסה של Dog של Speak(). זה נקרא פולימורפיזם בזמן ריצה — המתודה שנקראת בפועל תלויה בסוג האמיתי של האובייקט, ולא בסוג המוצהר של המשתנה.
עדיין אפשר לגשת למימוש הבסיסי באמצעות base.Speak() בתוך המימוש מחדש, אם רוצים להרחיב את ההתנהגות במקום להחליף אותה לגמרי.
אתגר
קלבואו נבנה מערכת התראות שמדגימה כיצד מחלקות נגזרות יכולות לדרוס לחלוטין את ההתנהגות של מחלקת הבסיס באמצעות מילות המפתח virtual ו-override, ובמקביל להציג את העוצמה של פולימורפיזם בזמן ריצה.
תיצרו שלושה קבצים כדי לארגן את הקוד:
Notification.cs: הגדירו מחלקה בשםNotificationבמרחב השמותAlerts. מחלקת בסיס זו מייצגת התראה כללית, עם מאפייןMessage(מחרוזת) ובנאי שמגדיר אותו. כללו מתודה בשםSend()עם מילת המפתחvirtual, שמחזירה את"Sending notification: {Message}".EmailNotification.cs: הגדירו מחלקה בשםEmailNotificationבמרחב השמותAlerts, שיורשת מ-Notification. הוסיפו מאפייןRecipient(מחרוזת) ובנאי שמקבל גם הודעה וגם נמען (השתמשו ב-baseכדי להעביר את ההודעה). דרסו את המתודהSend()כך שתחזיר את"Emailing {Recipient}: {Message}".SmsNotification.cs: הגדירו מחלקה בשםSmsNotificationבמרחב השמותAlerts, שיורשת גם היא מ-Notification. הוסיפו מאפייןPhoneNumber(מחרוזת) ובנאי שמקבל גם הודעה וגם מספר טלפון. דרסו אתSend()כך שתחזיר את"SMS to {PhoneNumber}: {Message}".Program.cs: בקובץ הראשי, צרו מופעים של שלושת סוגי ההתראות באמצעות ערכי קלט. לאחר מכן הדגימו פולימורפיזם בזמן ריצה על ידי אחסון של שלושתם במשתנים מסוגNotificationוקריאה ל-Send()בכל אחד מהם.
תקבלו ארבעה קלטים:
- הודעת ההתראה
- כתובת הנמען של הדוא״ל
- מספר טלפון עבור SMS
הדפיסו את התוצאה של קריאה ל-Send() בכל אחת מההתראות, המאוחסנות כהפניות למחלקת הבסיס:
{base notification Send() result}
{email notification Send() result}
{sms notification Send() result}לדוגמה, אם הקלטים הם Meeting at 3pm, alice@email.com ו-555-1234, הפלט אמור להיות:
Sending notification: Meeting at 3pm
Emailing alice@email.com: Meeting at 3pm
SMS to 555-1234: Meeting at 3pmשימו לב: אף על פי שכל השלושה מאוחסנים במשתנים מסוג Notification, כל אחד מהם קורא לגרסה משלו של Send() שנדרסה. זהו פולימורפיזם בזמן ריצה בפעולה!
נסו בעצמכם
using System;
using Alerts;
class Program
{
public static void Main(string[] args)
{
// קרא את הקלטים
string message = Console.ReadLine();
string email = Console.ReadLine();
string phone = Console.ReadLine();
// TODO: צור מופעים של כל שלושת סוגי ההתראות
// אחסן אותם במשתנים מסוג Notification כדי להדגים פולימורפיזם
// TODO: צור אובייקט בסיסי מסוג Notification
Notification baseNotification;
// TODO: צור אובייקט מסוג EmailNotification (שמאוחסן כטיפוס Notification)
Notification emailNotification;
// TODO: צור אובייקט מסוג SmsNotification (שמאוחסן כטיפוס Notification)
Notification smsNotification;
// TODO: קרא ל-Send() עבור כל אחד מהם והדפס את התוצאות
// המתודות שנדרסו ייקראו בזכות פולימורפיזם בזמן ריצה
}
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות התכנות מונחה העצמים
קבצים חיצונייםמרחבי שמות והנחיותמבוא למחלקות ולאובייקטיםמילת המפתח 'this'מתודות ופרמטריםשדות לעומת מאפייניםבנאיםאתחול אובייקטיםסיכום – מחשבון פשוט4ירושה
תחביר ירושה בסיסית (:)מילת המפתח 'base'מילות המפתח Virtual ו-Overrideמחלקות Sealedמחלקת הבסיס 'object'סיכום – היררכיית עובדים7תכונות מתקדמות
העמסת אופרטוריםאינדקסרים (this[])דריסת ToString()מתודות הרחבהסיכום – רשימה מותאמת אישית2מאפיינים וחברים סטטיים
מאפיינים במימוש אוטומטימאפיינים לקריאה בלבד ולכתיבה בלבדשדות ומתודות סטטייםמחלקות סטטיותחברים עם גוף ביטוי5פולימורפיזם וממשקים
פולימורפיזם בזמן קומפילציה לעומת בזמן ריצהממשק לעומת מחלקה מופשטתממשקים מרוביםממשקים מפורשיםהמרה כלפי מעלה והמרה כלפי מטהחזרה: מחשבון צורות8מושגים מתקדמים בתכנות מונחה עצמים
קומפוזיציה במקום ירושהGenerics (מחלקות ומתודות)נציגים ואירועיםמאפיינים ורפלקציהIDisposable והצהרת usingיסודות הזרקת תלויותתרגלו בעצמכם: קומפיילר C# אונליין