On this page
מערך שיעור: Interfaces — ממשקים
משך: 2 שעות אקדמיות (90 דקות).
מטרת השיעור: הסטודנטים יבינו מתי להשתמש ב-Interface לעומת ירושה, ויממשו IComparable בביטחון.
בסוף השיעור הסטודנטים צריכים: להגדיר ולממש Interface מותאם אישית, לממש IComparable<T> כדי לאפשר מיון, ולהסביר את ההבדל בין “הוא-סוג-של” ל"יודע-לעשות".
דגש קריטי: פתחו עם .Sort() שלא עובד על מחלקה מותאמת אישית (“איך .NET אמור לדעת מה ‘לפני’ אומר עבור Student?”) — זו הבעיה הקונקרטית שמצדיקה את כל השיעור.
מהלך השיעור
| חלק בשיעור | משך | הערות ודגשים |
|---|---|---|
| פתיחה וחיבור | 5 דקות | נסו students.Sort() בלי IComparable — שגיאת קומפילציה |
| הבעיה: .NET לא יודע להשוות | 10 דקות | הדגישו ש-Sort() גנרית לגמרי, לא “יודעת” כלום על Student |
| הרעיון: Interface | 15 דקות | הגדרה כללית, לפני IComparable הספציפי |
| IComparable בפועל | 20 דקות | מימוש CompareTo, הרצת Sort() בהצלחה |
| Interface מול Abstract Class | 15 דקות | טבלת השוואה — “מה” מול “מה+איך” |
| כמה 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(); שמקבלת כל דבר שיודע לעוף, בלי לדעת אם זה ברווז או מטוס.