משך: 2 שעות אקדמיות (90 דקות).

מטרת השיעור: הסטודנטים יבינו מתי להשתמש ב-Interface לעומת ירושה, ויממשו IComparable בביטחון.

בסוף השיעור הסטודנטים צריכים: להגדיר ולממש Interface מותאם אישית, לממש IComparable<T> כדי לאפשר מיון, ולהסביר את ההבדל בין “הוא-סוג-של” ל"יודע-לעשות".

דגש קריטי: פתחו עם .Sort() שלא עובד על מחלקה מותאמת אישית (“איך .NET אמור לדעת מה ‘לפני’ אומר עבור Student?”) — זו הבעיה הקונקרטית שמצדיקה את כל השיעור.


מהלך השיעור

חלק בשיעורמשךהערות ודגשים
פתיחה וחיבור5 דקותנסו students.Sort() בלי IComparable — שגיאת קומפילציה
הבעיה: .NET לא יודע להשוות10 דקותהדגישו ש-Sort() גנרית לגמרי, לא “יודעת” כלום על Student
הרעיון: Interface15 דקותהגדרה כללית, לפני IComparable הספציפי
IComparable בפועל20 דקותמימוש CompareTo, הרצת Sort() בהצלחה
Interface מול Abstract Class15 דקותטבלת השוואה — “מה” מול “מה+איך”
כמה Interfaces יחד10 דקותדוגמת IPrintable+ISaveable
תרגול מודרך15 דקותתרגיל 1+2

דגשים להעברת השיעור

  • ההבדל בין Interface ל-Abstract Class הוא נקודת הבלבול המרכזית בשיעור הזה — טבלת השוואה ברורה (Interface = חוזה טהור, Abstract = יכול לכלול מימוש) שווה זמן.
  • קשרו את IComparable בחזרה ל-.Sort() שכבר מוכר מ-List<T> — הראו שזו אותה .Sort() בדיוק שכבר השתמשו בה על List<int> (עם השוואה מובנית), עכשיו על טיפוס מותאם אישית.
  • אל תרחיבו לגנריקה מלאה (IComparable<T> עם ה-<T>) יותר מדי — Generics מגיעים בשיעור נפרד ביחידה הבאה, כאן מספיק להשתמש בו כמו שהוא.

מושגים

Interface — חוזה: רשימת מתודות/Properties בלי מימוש, שכל מממש מתחייב לספק. IComparable<T> — Interface מובנה ב-.NET שמאפשר מיון עם CompareTo. Interface מול Abstract Class — חוזה טהור מול תבנית עם מימוש חלקי.


תרגיל חשיבה

שאלת פתיחה: “Duck (ברווז) יכול לעוף וגם לשחות. Airplane (מטוס) יכול לעוף אבל לא לשחות. יש קשר משפחתי (ירושה) בין ברווז למטוס? איך בכל זאת מבטאים שלשניהם ‘יכולת לעוף’ משותפת?”

מהלך: הובילו את הסטודנטים לזהות שאין קשר “הוא-סוג-של” הגיוני בין ברווז למטוס — אבל יש להם התנהגות משותפת (Fly()). זו בדיוק הדוגמה הקלאסית ל"למה Interface ולא ירושה" — IFlyable יכול להיות ממומש גם ב-Duck וגם ב-Airplane, בלי לקשור ביניהם משפחתית.

מה המרצה מראה בסוף: ממשו interface IFlyable { void Fly(); } בשתי מחלקות שונות לגמרי (Duck ו-Airplane, בלי Base Class משותפת), וכתבו פונקציה void LetItFly(IFlyable flyable) => flyable.Fly(); שמקבלת כל דבר שיודע לעוף, בלי לדעת אם זה ברווז או מטוס.