370. Single Abstract Methods

למי שלא יודע, עד היום אין בJava תמיכה בDelegateים.

התמיכה תכנס בJava 8, הגרסה הבאה שתצא. (אם אני לא טועה, היא מתוכננת לקיץ הבא)

אני רוצה לדבר על איך זה הולך לעבוד.


איך זה עובד בC#? למי שזוכר ומי שלא, בC# אנחנו מגדירים אובייקטים מיוחדים שנקראים Delegateים, ע”י המילה השמורה delegate:

1
public delegate int NumericFunction(int value);

ואז אנחנו יכולים להשתמש בטיפוס בזה – לקבל אותו כפרמטר בפונקציה, לאתחל אותו במשתנה, ולבסוף גם להריץ את הDelegate.

מה שקורה מאחורי הקלעים זה שכל Delegate בעצם מתקמפל למחלקה.

כאשר אנחנו כותבים קוד כזה:

1
2
3
4
public int MyFunctionAt3(NumericFunction myFunction)
{
return myFunction(3);
}

הוא מתקמפל לקוד הזה:

1
2
3
4
public int MyFunctionAt3(NumericFunction myFunction)
{
return myFunction.Invoke(3);
}

אנחנו נהנים מהיכולת של הקומפיילר להסוות לנו את העובדה שנוצרת מחלקה מאחורי הקלעים, ושאנחנו מפעילים את הפונקציה Invoke, וכך אנחנו כותבים פחות קוד. (למעשה, ע"י שימוש בFunc/Action, כמעט ואין לנו צורך לכתוב Delegateים משלנו, ראו גם טיפ מספר 46-47)


בJava 8 לא יוסיפו מילה שמורה חדשה בשם Delegate. אז מה יהיה במקום?

הרעיון הוא אותו רעיון, אבל קצת שונה. נניח שאנחנו רוצים לכתוב פונקציה שמקבלת הצבעה לפונקציה אחרת, למשל עם החתימה שהשתמשנו בה כאן.

מה שנאלץ לעשות זה ליצור משהו שנקרא SAM – אלה ראשי תיבות של Single abstract method.

זה ממשק שיש לו מתודה בודדת, למשל:

1
2
3
4
interface NumericFunction
{
public int calculate(int value);
}

את הפונקציה הקודמת נכתוב ככה:

1
2
3
4
public int myFunctionAt3(NumericFunction myFunction)
{
return myFunction.calculate(3);
}

והקומפיילר של Java ידע לתרגם Referenceים למתודות לממשק שלנו.

היתרון הוא שיש פה יותר הבנה של מה שקורה.

החסרון הוא שזה פחות נוח למשתמש – צריך לכתוב ממשק עבור כל Delegate, וקוראים למתודה דרך מתודה של הממשק.


המשך שבוע עם קפה רותח טוב.

שתף