Menu
CoddyTech

מילות המפתח 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() בתוך המימוש מחדש, אם רוצים להרחיב את ההתנהגות במקום להחליף אותה לגמרי.

challenge icon

אתגר

קל

בואו נבנה מערכת התראות שמדגימה כיצד מחלקות נגזרות יכולות לדרוס לחלוטין את ההתנהגות של מחלקת הבסיס באמצעות מילות המפתח 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() עבור כל אחד מהם והדפס את התוצאות
        // המתודות שנדרסו ייקראו בזכות פולימורפיזם בזמן ריצה
    }
}
quiz iconבחנו את עצמכם

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

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

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