פולימורפיזם בזמן קומפילציה לעומת בזמן ריצה
חלק מהיחידה תכנות מונחה עצמים במסלול ה-C# של Coddy. שיעור 25 מתוך 70.
פולימורפיזם פירושו "צורות רבות" — היכולת של אותו קוד להתנהג באופן שונה בהתאם להקשר. C# תומכת בשני סוגים נפרדים של פולימורפיזם, והבנת המועד שבו כל אחד מהם נקבע עוזרת לך לכתוב קוד גמיש יותר.
פולימורפיזם בזמן קומפילציה (נקרא גם פולימורפיזם סטטי) נפתר על ידי המהדר לפני שהתוכנית שלך רצה. העמסת מתודות היא הדוגמה העיקרית — כמה מתודות חולקות את אותו שם, אך מקבלות פרמטרים שונים:
public class Calculator
{
public int Add(int a, int b) => a + b;
public double Add(double a, double b) => a + b;
}
var calc = new Calculator();
calc.Add(5, 3); // המהדר בוחר בגרסת int
calc.Add(5.0, 3.0); // המהדר בוחר בגרסת doubleהמהדר בוחן את סוגי הארגומנטים ובוחר את המתודה המתאימה בזמן הידור. ההחלטה הזאת נקבעת לפני שהתוכנית מתחילה לפעול.
פולימורפיזם בזמן ריצה (פולימורפיזם דינמי) מוכרע בזמן שהתוכנית רצה. הדבר מתרחש באמצעות מתודות virtual ו-override — הטיפוס בפועל של האובייקט קובע איזו מתודה תתבצע:
Animal pet = new Dog(); // הוצהר כ-Animal, אך בפועל הוא Dog
pet.Speak(); // קורא ל-Speak() של Dog בזמן ריצההמהדר לא יודע איזו Speak() תרוץ — ההחלטה מתקבלת בזמן הריצה על סמך הטיפוס האמיתי של האובייקט. זה מה שהופך פולימורפיזם המבוסס על ירושה לעוצמתי כל כך לבניית מערכות גמישות וניתנות להרחבה.
אתגר
קלנבנה מערכת המרה שמדגימה את שני סוגי הפולימורפיזם בפעולה. תיצור מחלקה שמשתמשת בהעמסת מתודות (פולימורפיזם בזמן הידור), לצד היררכיית ירושה שמשתמשת במתודות virtual/override (פולימורפיזם בזמן ריצה).
תארגן את הקוד שלך בארבעה קבצים:
Converter.cs: הגדר מחלקה בשםConverterבמרחב השמותConversion. המחלקה מדגימה פולימורפיזם בזמן הידור באמצעות העמסת מתודות. צור שלוש מתודותConvertמועמסות:Convert(int value)מחזירה"Integer: {value}"Convert(double value)מחזירה"Double: {value}"Convert(string value)מחזירה"String: {value}"
Shape.cs: הגדר מחלקת בסיס בשםShapeבמרחב השמותConversion. למחלקה יש מאפייןName(מחרוזת) ובנאי שמגדיר אותו. כלול מתודתvirtualבשםDescribe()שמחזירה"This is a {Name}".Circle.cs: הגדר מחלקה בשםCircleבמרחב השמותConversionשיורשת מ־Shape. הוסף מאפייןRadius(double). הבנאי מקבל רדיוס ומעביר את"Circle"לבנאי של מחלקת הבסיס. בצע override למתודהDescribe()כך שתחזיר"This is a Circle with radius {Radius}".Program.cs: בקובץ הראשי שלך, הדגם את שני סוגי הפולימורפיזם. תחילה, צור מופע שלConverterוקרא לכל שלוש המתודות המועמסות עם ערכי קלט. לאחר מכן, צור מופע שלCircle, אחסן אותו במשתנה מסוגShapeוקרא ל־Describe()כדי להציג פולימורפיזם בזמן ריצה.
תקבל ארבעה ערכי קלט:
- ערך של מספר שלם
- ערך מסוג double
- ערך של מחרוזת
- רדיוס של מעגל (double)
הדפס את הפלט בפורמט הבא:
Compile-time Polymorphism:
{Convert(int) result}
{Convert(double) result}
{Convert(string) result}
Runtime Polymorphism:
{Describe() result from Shape variable holding Circle}לדוגמה, אם ערכי הקלט הם 42, 3.14, Hello ו־5.5, הפלט אמור להיות:
Compile-time Polymorphism:
Integer: 42
Double: 3.14
String: Hello
Runtime Polymorphism:
This is a Circle with radius 5.5שים לב להבדל המרכזי: המהדר מחליט לאיזו מתודת Convert לקרוא על סמך סוגי הארגומנטים בזמן ההידור, בעוד שהמתודה Describe() נקבעת בזמן ריצה על סמך הסוג של האובייקט בפועל, אף על פי שהוא מאוחסן במשתנה מסוג Shape!
נסו בעצמכם
using System;
using Conversion;
class Program
{
public static void Main(string[] args)
{
// קראו את הקלטים
int intValue = Convert.ToInt32(Console.ReadLine());
double doubleValue = Convert.ToDouble(Console.ReadLine());
string stringValue = Console.ReadLine();
double radius = Convert.ToDouble(Console.ReadLine());
// TODO: הדגימו פולימורפיזם בזמן קומפילציה
// צרו אובייקט מסוג Converter וקראו לכל שלוש הגרסאות של המתודה Convert
Console.WriteLine("Compile-time Polymorphism:");
// קראו ל-Convert עם intValue, doubleValue ו-stringValue
// TODO: הדגימו פולימורפיזם בזמן ריצה
// צרו אובייקט מסוג Circle ושמרו אותו במשתנה מסוג Shape
// לאחר מכן קראו ל-Describe() על המשתנה מסוג Shape
Console.WriteLine("Runtime Polymorphism:");
// צרו אובייקט מסוג Circle וקראו ל-Describe()
}
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות התכנות מונחה העצמים
קבצים חיצונייםמרחבי שמות והנחיותמבוא למחלקות ולאובייקטיםמילת המפתח 'this'מתודות ופרמטריםשדות לעומת מאפייניםבנאיםאתחול אובייקטיםסיכום – מחשבון פשוט4ירושה
תחביר ירושה בסיסית (:)מילת המפתח 'base'מילות המפתח Virtual ו-Overrideמחלקות Sealedמחלקת הבסיס 'object'סיכום – היררכיית עובדים7תכונות מתקדמות
העמסת אופרטוריםאינדקסרים (this[])דריסת ToString()מתודות הרחבהסיכום – רשימה מותאמת אישית2מאפיינים וחברים סטטיים
מאפיינים במימוש אוטומטימאפיינים לקריאה בלבד ולכתיבה בלבדשדות ומתודות סטטייםמחלקות סטטיותחברים עם גוף ביטוי5פולימורפיזם וממשקים
פולימורפיזם בזמן קומפילציה לעומת בזמן ריצהממשק לעומת מחלקה מופשטתממשקים מרוביםממשקים מפורשיםהמרה כלפי מעלה והמרה כלפי מטהחזרה: מחשבון צורות8מושגים מתקדמים בתכנות מונחה עצמים
קומפוזיציה במקום ירושהGenerics (מחלקות ומתודות)נציגים ואירועיםמאפיינים ורפלקציהIDisposable והצהרת usingיסודות הזרקת תלויותתרגלו בעצמכם: קומפיילר C# אונליין