נציגים ואירועים
חלק מהיחידה תכנות מונחה עצמים במסלול ה-C# של Coddy. שיעור 43 מתוך 70.
נציג הוא טיפוס שמייצג הפניה למתודה. אפשר לחשוב עליו כעל משתנה שמחזיק מתודה במקום נתונים. כך ניתן להעביר מתודות כארגומנטים, לאחסן אותן באוספים ולקרוא להן באופן דינמי.
מכריזים על נציג באמצעות ציון חתימת המתודה שאליה הוא יכול להפנות:
public delegate void Notify(string message);
public class Publisher
{
public void SendAlert(string msg) => Console.WriteLine("Alert: " + msg);
}
// שימוש
Notify notifier = new Publisher().SendAlert;
notifier("System started"); // Alert: System startedאירועים מתבססים על נציגים כדי לממש את דפוס הפרסום-הרשמה. מחלקה מעוררת אירוע, ומחלקות אחרות יכולות להירשם כדי לקבל הודעות. מילת המפתח event מגבילה את אופן השימוש בנציג — מנויים יכולים רק להוסיף מטפלים או להסיר אותם, ולא להפעיל את האירוע ישירות.
public class Button
{
public event Action Clicked;
public void Click()
{
Clicked?.Invoke(); // הודע לכל המנויים
}
}
// הרשמה לאירוע
Button btn = new Button();
btn.Clicked += () => Console.WriteLine("Button was clicked!");
btn.Click(); // בוצעה לחיצה על הכפתור!האופרטור += רושם מטפל, ואילו -= מבטל את הרישום שלו. התבנית ?.Invoke() קוראת לאירוע בבטחה רק אם יש לו מנויים. אירועים הם יסודיים ביישומי GUI, במנועי משחקים ובכל מערכת שבה אובייקטים צריכים להגיב לשינויים ללא צימוד הדוק.
אתגר
קלבואו נבנה מערכת לניטור טמפרטורה שמשתמשת בנציגים ובאירועים כדי להודיע למנויים בכל פעם שהטמפרטורה משתנה. זוהי דוגמה קלאסית לדפוס פרסום-מינוי שאירועים מאפשרים בצורה אלגנטית כל כך.
תארגנו את הקוד שלכם בשני קבצים:
TemperatureMonitor.cs: צרו מחלקה בשםTemperatureMonitorבמרחב השמותMonitoring, שתשמש כמפרסם. המנטר שלכם צריך:- להכיל שדה פרטי לאחסון הטמפרטורה הנוכחית
- להצהיר על אירוע באמצעות
Action<int>בשםTemperatureChanged, שמופעל בכל פעם שהטמפרטורה מתעדכנת - להכיל מאפיין
Temperatureמסוג int, שבו הקובע מעדכן את השדה הפרטי ומפעיל את האירוע עם ערך הטמפרטורה החדש
?.Invoke()כדי להפעיל את האירוע בבטחה רק כשיש מנויים.Program.cs: בקובץ הראשי שלכם, צרו מופע שלTemperatureMonitorורשמו שני מטפלים שונים לאירועTemperatureChangedשלו:- מטפל אחד שמדפיס:
Alert: Temperature is now {value} degrees - מטפל נוסף שמדפיס:
Logged: {value}
- מטפל אחד שמדפיס:
תקבלו שני קלטים:
- ערך הטמפרטורה הראשון (מספר שלם)
- ערך הטמפרטורה השני (מספר שלם)
לדוגמה, אם הקלטים הם 25 ו-30, הפלט אמור להיות:
Alert: Temperature is now 25 degrees
Logged: 25
Alert: Temperature is now 30 degrees
Logged: 30שימו לב כיצד הגדרת המאפיין Temperature מודיעה אוטומטית לכל המנויים — המנטר לא צריך לדעת דבר על מי שמאזין. זה היופי בגישה מבוססת האירועים!
נסו בעצמכם
using System;
using Monitoring;
class Program
{
public static void Main(string[] args)
{
// קרא את הקלט
int temp1 = Convert.ToInt32(Console.ReadLine());
int temp2 = Convert.ToInt32(Console.ReadLine());
// TODO: צור מופע של TemperatureMonitor
// TODO: רשום מטפל שמדפיס: "Alert: Temperature is now {value} degrees"
// TODO: רשום מטפל נוסף שמדפיס: "Logged: {value}"
// TODO: הגדר את הטמפרטורה ל-temp1
// TODO: הגדר את הטמפרטורה ל-temp2
}
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות התכנות מונחה העצמים
קבצים חיצונייםמרחבי שמות והנחיותמבוא למחלקות ולאובייקטיםמילת המפתח 'this'מתודות ופרמטריםשדות לעומת מאפייניםבנאיםאתחול אובייקטיםסיכום – מחשבון פשוט4ירושה
תחביר ירושה בסיסית (:)מילת המפתח 'base'מילות המפתח Virtual ו-Overrideמחלקות Sealedמחלקת הבסיס 'object'סיכום – היררכיית עובדים7תכונות מתקדמות
העמסת אופרטוריםאינדקסרים (this[])דריסת ToString()מתודות הרחבהסיכום – רשימה מותאמת אישית2מאפיינים וחברים סטטיים
מאפיינים במימוש אוטומטימאפיינים לקריאה בלבד ולכתיבה בלבדשדות ומתודות סטטייםמחלקות סטטיותחברים עם גוף ביטוי5פולימורפיזם וממשקים
פולימורפיזם בזמן קומפילציה לעומת בזמן ריצהממשק לעומת מחלקה מופשטתממשקים מרוביםממשקים מפורשיםהמרה כלפי מעלה והמרה כלפי מטהחזרה: מחשבון צורות8מושגים מתקדמים בתכנות מונחה עצמים
קומפוזיציה במקום ירושהGenerics (מחלקות ומתודות)נציגים ואירועיםמאפיינים ורפלקציהIDisposable והצהרת usingיסודות הזרקת תלויותתרגלו בעצמכם: קומפיילר C# אונליין