ונדאג בConstructorים לאתחל את הDelegate במתודות הנכונות:
בShape זה קל:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
publicShape()
{
mGetArea = InnerGetArea;
mGetPerimeter = InnerGetPerimeter;
}
publicstaticdoubleInnerGetPerimeter(Shape _this)
{
return0;
}
publicstaticdoubleInnerGetArea(Shape _this)
{
return0;
}
בSquare זה יותר קשה:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
publicSquare()
{
mGetArea = InnerGetArea;
mGetPerimeter = InnerGetPerimeter;
}
publicstaticdoubleInnerGetPerimeter(Shape _this)
{
return GetPerimeter((Square) _this);
}
publicstaticdoubleInnerGetArea(Shape _this)
{
return GetArea((Square)_this);
}
publicstaticdoubleGetArea(Square _this)
{
return _this.Edge*_this.Edge;
}
publicstaticdoubleGetPerimeter(Square _this)
{
return4*_this.Edge;
}
שימו לקסם: כשיכתבו את השורה הזאת למשל:
1
2
Shape shape = new Square() { Edge = 3 };
shape.GetPerimeter(); // 12
היא תתרגם ל
1
2
Shape shape = new Square() { Edge = 3 };
Shape.GetPerimeter(shape);
שתקרא ל
1
2
3
4
publicstaticdoubleGetPerimiter(Shape _this)
{
return _this.mGetPerimeter(_this);
}
שתקרא ל
1
2
3
4
publicstaticdoubleInnerGetPerimeter(Shape _this)
{
return GetPerimeter((Square) _this);
}
שתקרא ל
1
2
3
4
publicstaticdoubleGetPerimeter(Square _this)
{
return4*_this.Edge;
}
הקסם הוא שהמתודה היחידה שיש לנו כאן שהיא באמת "וירטואלית" היא הConstructor. וזה לגיטימי שהיא תהיה וירטואלית, כי הרי אנחנו יוצרים עם Constructorים שונים אובייקטים שונים.
הפתרון הזה נחמד, ואם יצא לכם לתכנת בשפות אחרות, קיימת סבירות גבוהה שכך ממומשות שם פונקציות וירטואליות.
אם נחשוב על זה, כעת כל instance שלנו מתנפח במידה אודות כל הפונקציות הוירטואליות שיש לו. זה בסדר עבור delegate אחד או שניים, אבל ברגע שזה גדל, זה מתחיל לתפוס מקום בזכרון.
בפעם הבאה אנחנו ננסה להקטין את המקום הזה בזכרון ע"י יצירת הDelegateים האלה פעם אחת.