ניקח את הדוגמא הבאה: 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)באופן אוטומטי יקרא לגרסה שלכם.