דיברנו קצת על Single dynamic dispatch.
זהו כאמור קונספט המאפשר לנו להחליט בזמן ריצה איזו מתודה להפעיל.
מה בדיוק Single כאן?
ובכן, ההחלטה איזו מתודה להפעיל בזמן ריצה, נקבע עפ”י פרמטר יחיד – הטיפוס של הinstance שעליו אנו מפעילים את המתודה.
קיים קונספט מוכלל דומה שנקרא Multiple dynamic dispatch. הרעיון הוא שהניתוב למתודה בזמן ריצה לא נקבע עפ”י פרמטר בודד (הטיפוס של הinstance עליו מופעלת המתודה), אלא עפ”י מספר פרמטרים, שהם חלק מהטיפוסים שנשלחו לפונקציה.
למה הכוונה?
נניח שיש לנו את הפונקציה הבאה:
|
|
זו פונקציה שמקבלת שתי צורות, וחוסמת צורה אחת בתוך השנייה.
עכשיו, אנחנו יכולים ליצור את מגוון הOverloadים הבאים:
|
|
אלה מספר אפשרויות של לחסום מעגל בתוך ריבוע או משולש, או לחסום משולש/ריבוע במעגל.
בזמן קימפול אם נכתוב קוד כזה:
|
|
הקומפיילר ידע לנתב אותנו לOverload המתאים ביותר, במקרה שלנו ל
|
|
היינו רוצים שגם אם נכתוב קוד כזה:
|
|
ושהמתודה עם הOverload המתאים ביותר תבחר בזמן ריצה, שהרי כרגע תמיד נבחר הOverload
|
|
לקונספט הזה של בחירת מתודה בזמן ריצה עפ"י סוגי הפרמטרים, קוראים Multiple dynamic dispatch.
איך אפשר להשיג את זה בC#? עד C# 3.0 צריך לעבוד קצת קשה כדי לעשות משהו כזה:
|
|
מה קורה כאן? אנחנו מחפשים בתוך המחלקה שלנו מתודה בשם InscribeInShape עם פרמטרים מהטיפוס של הפרמטרים שקיבלנו לפונקציה. (ראו גם טיפ מספר 137, 147)
לאחר מכן אנחנו מפעילים את הפונקציה עם הפרמטרים הנ"ל (ראו גם טיפ מספר 148)
מה הסוד כאן? הסוד הוא שהפונקציה GetMethod יודעת למצוא את הOverload שהכי מתאים לטיפוסים שאנחנו נותנים לה, בדומה לקומפיילר שבזמן קימפול מוצא את הOverload עם טיפוסי הפרמטרים הכי מתאימים.
מה זאת אומרת? אם, למשל, תהיה לנו את ההיררכיה הבאה:
|
|
ויהיו לנו רק את הOverloadים הבאים:
|
|
אז הקוד הבא:
|
|
יכנס לOverload
|
|
למרות הType הקונקרטי של someShape הוא Circle, ולא Ellipse.
זה די מגניב!
יש שפות שבהן שימוש בMultiple dispatch הוא יותר פשוט.
בשפת C# 4.0 נכנסה תמיכה לתוך השפה, כך שהרבה יותר קל להשתמש בזה.
הכלי הזה הוא חזק ומכליל את המושג של פונקציות וירטואליות שהתרגלנו להשתמש בו כבר.
ראו גם ב Wiki.
המשך יום דינאמי מרובה טוב!