ניקח את הדוגמא הבאה: Console.WriteLine(myInstance.ToString())
מדוע תופעל הפעולה מהמחלקה היורשת גם אם אין override?
העניין קשור ישירות לאופן שבו Console.WriteLine
עובד ב-C# ולמנגנון ההדפסה הפנימי שלו.
1. מה קורה בלי override
כאשר אתם יוצרים מחלקה עם פעולה ()ToString
בלי מילת המפתח override
, בעצם יצרתם פעולה חדשה שמסתירה (hides
) את הפעולה הווירטואלית שהוגדרה במחלקת הבסיס (()object.ToString
).
במקרה זה:
class MyClass {
public string ToString() { return "My version"; } // לא override
}
-
כאשר אתם כותבים:
Console.WriteLine(myInstance.ToString());
אתם קוראים ישירות לגרסה שלכם, כי אתם מכריחים את הקומפיילר לבחור בפעולה הזו.
-
אבל כשאתם כותבים:
Console.WriteLine(myInstance);
כאן מה שקורה בפועל הוא שהקומפיילר בוחר באוברלואד
Console.WriteLine(object value)
, שבתוכו יש קריאה ל-()value.ToString
. הפעולה שהוא מפעיל היא ה-virtual ToString
שהוגדרה ב-object
. מאחר שלא ביצעתםoverride
, המימוש של()object.ToString
רץ ולא שלכם.
2. מה קורה עם override
כאשר אתם מוסיפים:
public override string ToString() { return "My version"; }
אתם באמת מחליפים את המימוש הווירטואלי של ()object.ToString
.
עכשיו גם אם הקוד מגיע מ־Console.WriteLine(object value)
⟵ הקריאה ל-()value.ToString
מתבצעת פולימורפית לפי סוג האובייקט בפועל.
לכן ההדפסה תשתמש במימוש שלכם גם אם לא קראתם לו במפורש.
3. אפשר להסביר זאת כך:
- בלי override ⟵ כתבנו פעולה חדשה, אבל
Console.WriteLine
לא מכיר אותה אלא אם כן קראתם לה במפורש. - עם override ⟵ שינינו את החוק הבסיסי של
.()ToString
בכל אובייקט מהמחלקה שלכם ⟵ ולכן גםConsole.WriteLine(myInstance)
באופן אוטומטי יקרא לגרסה שלכם.