פולימורפיזם (תוכנה)

מתוך ויקיפדיה, האנציקלופדיה החופשית
קפיצה אל: ניווט, חיפוש

במדעי המחשב, פולימורפיזםעברית: "רב צורתיות") הוא מאפיין בשפות תכנות, המסייע כתיבת תוכנה ברמות הפשטה שונות. פולימורפיזם מהווה תכונה חשובה במתודולוגית תכנות מונחה עצמים, אם כי לחלוטין איננו בלעדי למתודולוגיה זו. המנגנון נותן למתכנת את היכולת לממש אלגוריתמים ומבני נתונים לשימוש כללי, ולגזור מהם צורות שימוש שונות בהתאם לעצמים ולנסיבות המשתנות, באופן מפורש או מובלע. גם למנגנוני הכימוס וההורשה תפקיד בנתינת האפשרות לכתוב תוכנה כללית, ולעתים מנגנונים אלה משתלבים עם פולימורפיזם.

שפה התומכת בפולימורפיזם מאפשרת כתיבת תוכנה וחלקי תוכנה (כגון ספריות סטנדרטיות) כלליים וגמישים יותר, ונתינת משמעויות שונות לפעולה בהקשרים שונים, לעתים תוך חיסכון בשכפול קוד, וכך מאפשר להתייחס למכנה המשותף של משתנים או עצמים שונים. המשמעות של פעולה נקבעת בהקשר של כל אחד מטיפוסי הנתונים שעליהם מוגדרת פעולה זו, ובהתאם למשתנה או לעצם שבו עוסקת הפעולה.

תוכן עניינים

[עריכה] הרעיון הבסיסי

בהינתן אלגוריתם מסויים, למשל אלגוריתם למיון מערך, אין דרישה בסיסית באלגוריתם לדעת כל פרט על הטיפוס של אברי המערך. כל שיש לדעת הוא את גודל המערך, כיצד ניתן לבצע השוואה בין איברי המערך, וכיצד ניתן לשנות את הסדר שלהם. בשפות תכנות בעלות טיפוסיות חזקה וסטטית, שמקפידות על סוג המשתנה שמועבר לפרוצדורה, זו עשויה להיות בעיה: בכתיבת פרוצדורה שתמיין את איברי המערך, מאיזה טיפוס נגדיר את הפרמטרים שלה? יש צורך למצוא דרך להגדיר טיפוס מסוג גנרי כלשהו, שכל הידוע עליו הוא הנתונים החיוניים למימוש הפרוצדורה, ותו לא. ישנן שפות שמאפשרות זאת באמצעות מנגנון לזיהוי אוטומטי של הטיפוס של כל ביטוי (כמו למשל שפת התכנות ML), באמצעות טכניקות של ירושה ודריסה בתכנות מונחה עצמים, או באמצעות תכנות גנרי. כמו כן, כל שפה בעלת מערכת טיפוסים חלשה או דינמית, כגון פייתון, מאפשרת פולימורפיזם.

[עריכה] שפות שאינן מונחות עצמים

פולימורפיזם בצורתו הבסיסית ביותר קיים בכל שפת תכנות עילית. כאשר כותבים ביטויים כגון (4 + 4) או (5.3 + 2.1), אנו מנצלים את העובדה שאופרטור החיבור מועמס - כלומר, בעל משמעות כפולה - גם לטיפוס המשמש למספרים שלמים כמו 4, וגם לטיפוס המשמש לייצוג מספרים ממשיים כמו 2.1; זאת, למרות שהייצוג של מספרים אלו כביטים בשפת המכונה שונה לחלוטין בין מספרים שלמים למספרים ממשיים, ולכן גם פקודות המכונה המורות למעבד לבצע את פעולת החיבור תהיינה שונות; כל זה שקוף למתכנת, ולכן מקל על עבודתו.

שפת C מאפשרת צורה מוגבלת מאוד של פולימורפיזם, נוסף על העמסה בסיסית של אופרטורים אריתמטיים: בשפה מוגדרת המרה אוטומטית מכל טיפוס של מצביע אל הטיפוס הגנרי *void, ובחזרה. מנגנון זה מנוצל על ידי פונקציות כגון פונקציית הספריה הסטנדרטית qsort המשמשת למיון מערך, המקבלת מערך של מצביעים וממיינת אותו, תוך התייחסות אל כל המצביעים במערך כ-*void. טכניקה זו מאפשרת לבצע כל פעולה, אך היא איננה גמישה, ומצריכה מידע מפורש מהמתכנת בקשר לגודל של משתנים מהטיפוס שמועבר בפועל - מידע שאמור להימצא בידי המהדר בזמן הידור התוכנית, ולכן דורשת עבודה מיותרת. שפות אחרות, כגון שפת פסקל, לעתים אינן מאפשרות אפילו גנריות בסיסית כזאת.

כמו כן, ניתן לבצע פולימורפיזם בעזרת פקודות מאקרו, שמבצעות החלפה של טקסט מסויים בתוכנית בטקסט אחר, לפני ההידור. לדוגמה, המאקרו הבא בשפת C :

( (define min(x,y) ( ((x) < (y)) ? (x) : (y# 

מדמה פונקציה שמחזירה את המינימום מבין הביטויים המועברים אליה, ומתאימה לכל טיפוס עליו מוגדרת פעולת ההשוואה ">" (פעולה שבפני עצמה מועמסת, בדומה לאופרטור החיבור, ולכן פולימורפית). עם זאת, למאקרו כזה ישנם חסרונות רבים לעומת פונקציה אמתית: לא מתבצעת בדיקת טיפוסים, ביטוי עם תוצאת לוואי עלול לבצע אותה מספר פעמים, ולהחזיר תוצאה לא צפויה, ועוד.

בשפת ML, התומכת בפולימורפיזם מלא ומתוחכם, הדבר מתבצע כך: המתכנת כותב פונקציה, למשל פונקציה שהופכת רשימה, בדרך הטבעית לו, ללא הצהרה על הטיפוס אותו הפונקציה מקבלת. המהדר של השפה מסיק לבד, על פי הביטויים המשמשים בפונקציה, אילו טיפוסים ניתן להעביר אליה. טיפוסים אלה עשויים להיות קונקרטיים, כגון int שהוא מספר שלם, או גנריים, ואז הם יסומנו בתג ושם, למשל a' - זה בעצם "משתנה טיפוס" (type variable). המנגנון ידרוש עקביות: אם פונקציה מקבל שני ארגומנטים מטיפוס a', ניתן להעביר אליה שני משתנים שהם מספר שלם או שני משתנים שהם מספר ממשי, אך לעולם לא משתנה אחד ממשי ואחד שלם, כיוון ששני הארגומנטים חייבים להיות מאותו טיפוס.

[עריכה] פולימורפיזם בשפות מונחות עצמים

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

למשל, אף שיש מרחק רב בין מנוע של מעבורת חלל לבין מנוע של מכסחת דשא, באמצעות קונספט זה שיש בו הפשטה מושגית (מנוע יוגדר כמכונה הממירה אנרגיה לעבודה מכנית), אפשר להתייחס אליהם ואל מגוון האפשרויות שביניהם (מנועים של מטוס קרב סילוני, מטוס בואינג, מטוס קל, אוניה, טנק, משאית, מכונית, אופנוע, קטנוע), מתוך מחלקה תכנותית אחת, תוך ביצוע התאמות לכל אחד מהמנועים על פי המאפיינים הייחודיים שלו. גישה זו שיוצאת מהאבסטרקט ומגיע אל הקונקרטי ביותר (למשל בתיאור מפורט ומלא של מנוע מכונית מדגם מזדה 3), מונעת את הצורך לכתוב מחדש מחלקות נפרדות, עבור כל אחד ואחד מטיפוסי המנועים השונים, והיישומים המעשיים של כל אחד ואחד מהם (שהרי יש מנועי 4 פעימות של חברות שונות), ומסירה מהתכנות את הסרבול של הכתיבה החוזרת ונשנית ובכך הופכת אותו לריכוזי, יעיל ואלגנטי.

בתרשים הבא (שהינו חלקי ביותר וניתן לצורכי הדגמה) ניתן לראות שאפשר באמצעות פולימורפיזם לגזור התייחסויות רבות ומגוונות ממחלקה שמטפלת במנוע, לכל הטיפוסים והסוגים השונים של המנועים, במגוון הרחב שלהם, עד שאפשר להתייחס ממחלקה אחת, גם לטיפוס מנוע של מעבורת חלל וגם לטיפוס מנוע של מכסחת דשא, גם לטיפוס מנוע של מעלית וגשר נפתח וגם למנוע של מקדחה או מברגה, על אף השוני הגדול והתהומי שבין כל סוגי המנועים הללו. ההדגמה הזו של פולימורפיזם במנועים עשויה להראות עד כמה הגישה של הפולימורפיזם התכנותי נחוצה ומתאימה למורכבות הקיימת בעולם ובטכנולוגיה.


 
 
 
 
 
 
 
מנוע מכונה הממירה אנרגיה לעבודה מכנית. SWassermotor.png
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
מנוע חום
מנוע המונע באנרגיה תרמית
 
 
 
 
 
מנוע חשמלי מנוע המונע באנרגיה חשמלית Motors01CJC.jpg
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
מנוע רקטי - מנוע חום שכל החומרים הנחוצים לפעולתו נמצאים בתוכו
 
 
טורבינת גז J85 ge 17a turbojet engine.jpg
 
מנוע בוכנה - מנוע חום בו לחץ גזי השריפה דוחף בוכנה בתוך צילינדר Volkswagen W16.jpg
 
מקדחה
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
מנוע מעבורת חללAtlantis taking off on STS-27.jpg
 
מנוע סילון -מנוע בו לחץ גזי השריפה משמש ליצירת כוח דחף Iwtschenko AI-25 1.jpg
 
מנוע ארבע פעימות
 
 
מנוע שתי פעימות
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
מנוע מטוס קרב
F-15, 71st Fighter Squadron, in flight.JPG
 
מנוע מכונית
Mazda ZY-VE Engine.JPG
 
מנוע כלי טיס
 
מנוע מכסחת דשא
Electric mower underside.jpg
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
מנוע GMC
GMC Canyon Vortec 3500 engine 2.jpg

[עריכה] מנגנונים הרווחים ברב צורתיות

מנגנונים הרווחים ברב צורתיות, הם:

  • דריסה (Override) שבה ניתן להחליף פונקציה של מחלקת בסיס בפונקציה שונה במחלקה הנגזרת ממנה.באמצעות מנגנון זה ניתן להתאים את הפעולה לסוג המיוחד של האובייקט. שם הפעולה נשמר והיא מתבצעת בדרכים שונות בהתאם לאובייקט אליו היא מתייחסת. טכניקה נוספת היא הצללה שדומה ליכולת הדריסה.
  • העמסת פרמטרים, שבו ניתן ליצור כמה פונקציות בעלות שם זהה אך בעלות פרמטרים שונים. מנגנון זה שימושי לריכוז כל הפונקציות תחת אותה קורת גג, במקום לכתוב פונקציות רבות בעלות שם שונה שמבצעות למעשה את אותה פעולה מבחינה לוגית.
  • העמסת אופרטורים, היא מקרה פרטי של העמסת פונקציות, שבו אופרטור מסוים מקבל מכניזם פנימי שונה בתוך אובייקט. למשל אופרטור + שנועד לחבר מספרים, במחלקה של מחרוזות מקבל יכולת שרשור, ובמחלקה של מערכים יכול לקבל יכולת לחבר בין שני מערכים.

[עריכה] דוגמאות

כדי להדגים את הכוח של המנגנון, אפשר לחשוב על דוגמה שכיחה מחיי היום יום, אלגוריתם להחלפת גלגל ברכב:

  1. עצרו בצד והציבו סימנים המיידעים שהרכב בטיפול.
  2. הציבו את המגבה במקומו ושחררו מעט את ברגי הגלגל.
  3. הגביהו את הרכב בעזרת המגבה.
  4. פרקו את הגלגל והרכיבו במקומו גלגל תקין.
  5. חזקו מעט את הברגים.
  6. הנמיכו את הרכב עד שהגלגל יגע קלות בקרקע.
  7. חזקו את ברגי הגלגל בהצלבה.
  8. הנמיכו את הרכב, איספו את הכלים והמשיכו בנסיעה.

האלגוריתם, כפי שתואר, מתאים לכל סוג רכב, לאוטובוסים ומשאיות וגם למכוניות קטנות. כמעט כל פעולה המתוארת באלגוריתם תבוצע בצורה שונה בכל סוג רכב. הפעלת מגבה של אוטובוס, לדוגמה, שונה מאוד מהפעלת מגבה של מכונית קטנה. העובדה שהצלחנו לנסח אלגוריתם כללי (גנרי) לכל כלי הרכב למרות שבעצם בכל רכב האלגוריתם הוא אחר היא בזכות ההתייחסות המופשטת שלנו לרכב. בזמן שניסחנו את האלגוריתם לא התעניינו באיזה רכב מדובר אלא דיברנו על רכב כלשהו. כל דבר שאמרנו על רכב, דאגנו שיהיה נכון לכל רכב. לדוגמה, אמרנו "חזקו מעט את הברגים" ולא אמרנו "חזקו מעט את ארבעת הברגים".

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

דוגמה נוספת, מתחום המתמטיקה: אלגוריתם למציאת בסיס אורתונורמלי במרחב מכפלה פנימית (תהליך גרם שמידט). כאשר נתון בסיס קיים:

  1. בחרו וקטור כלשהו ונרמלו אותו.
  2. בחרו וקטור נוסף והטילו אותו על תת-המרחב הנפרש על ידי הווקטורים שכבר בחרתם.
  3. מצאו את ההפרש בין הווקטור להטלה שלו, נרמלו אותו והוסיפו אותו לרשימת הווקטורים שכבר נבחרו.
  4. חיזרו על הפעולות 2 ו-3 עד שיגמרו הווקטורים בבסיס המקורי. רשימת הווקטורים שנבחרו מהווה בסיס אורתונורמאלי למרחב.

כדי להיות וקטור יש למלא סט קצר של דרישות שיכול להתמלא על ידי אובייקטים מתמטיים שונים מאוד זה מזה. מכפלה פנימית גם היא יכולה להיות מוגדרת בדרכים רבות מאוד בעלות משמעויות שונות. הוכחת נכונות האלגוריתם מסתמכת רק על סט התכונות שמקיימים כל וקטור וכל מכפלה פנימית ולכן היא תקפה תמיד.

[עריכה] מימוש בתכנות

פולימורפיזם יכול להיות ממומש בזמן ריצה או בזמן קומפילציה. ב- C++‎ ממומש פולימורפיזם של זמן ריצה על ידי מצביע מסוג מופשט, המצביע לאובייקט קונקרטי. הקוד הבא מדגים איך ניתן לעשות זאת:

 class Car {...};
 
 class Bus: public Car{...};
 
 class PrivateCar: public Car{...};
 void changeWheel(Car *p) {
     p->stop();
     p->placeJack();
     p->lift();
     ...
 }
 int main() {
    Car* array[3];
    array[0]=new Bus();
    array[1]=new PrivateCar();
    array[2]=new Bus();
    for(int i=0;i<3; ++i)
       changeWheel(array[i]);
 }

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

הפונקציה מקבלת מצביע למכונית כללית. למעשה מדובר בסוג מסוים של מכונית, מכונית ספציפית, אבל changeWheel מתייחסת אליה פשוט כמכונית ומבצעת עליה רק פעולות שאפשר לעשות על כל מכונית. כאשר changeWheel תבקש ממכונית לעשות פעולה מסוימת, המכונית תבצע את הפעולה באופן ייחודי לה. ניתן לראות שהממשק למכונית מוגדר על ידי ההתייחסות המופשטת (המצביע למכונית כללית) ואילו הפעולה שתתבצע למעשה מוגדרת על ידי הטיפוס הספציפי (סוג המכונית).

כל הדברים הללו מתאימים לאופן שבו אנו משתמשים באבסטרקציה בחיי היום יום. נחשוב לדוגמה על המשפט: "בחדר ההמתנה צריך לשים מספר כיסאות בשביל שהלקוחות לא יצטרכו לחכות בעמידה". המשפט משתמש במושג המופשט "כיסא". יש המון סוגי כיסאות אבל המשפט מתייחס רק לתכונה המשותפת של כולם: כיסא מאפשר לשבת. כאשר המשפט ייושם, ייבחרו סוגים ספציפיים של כיסאות. אולי יהיו להם ארבע רגליים ואולי שלוש, אבל בכל מקרה הם יאפשרו ללקוחות להמתין בישיבה.

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

ב - ++C, פולימורפיזם של זמן קומפילציה ממומש על ידי template:

 class Bus {...};
 class PrivateCar {...};
 template<typename Car>
 void changeWheel(Car car){
    car.stop();
    car.placeJack();
    car.lift();
    ...
 }
 int main() {
    Bus bus;
    PrivateCar pcar;
    changeWheel(bus);
    changeWheel(pcar);
 }

כפי שניתן לראות, ניתן לקרוא לפונקציה changeWheel עם סוגים שונים של כלי-רכב. עבור כל סוג נפרשות בזמן קומפילציה הפונקציות המתאימות.

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

[עריכה] מימוש פולימורפיזם על ידי המהדר

נתבונן שוב בקטע הקוד המממש פולימורפיזם בזמן ריצה:

void changeWheel(Car *p) {
    p->stop();
    p->placeJack();
    p->lift();
    ...
}


נשאלת השאלה כיצד מתורגם קטע זה לשפת מכונה. לדוגמה הפעלת הפונקציה stop:

    p->stop();

בניגוד להפעלת פונקציה רגילה, בזמן הקומפילציה לא ידוע איזה קוד יש להפעיל. האם מדובר ב -() Bus::stop ,ב -() PrivateCar::stop או אולי פונקציית stop של טיפוס אחר. התשובה לשאלה זו מתבררת רק בזמן ריצה, כאשר ידוע על איזה טיפוס ספציפי מצביע p. הקומפיילר, אם כן, צריך לייצר קוד הקורא לפונקציה מסוימת בהתאם לטיפוס האובייקט שמוצבע על ידי p באותו הרגע. כדי לייצר קוד כזה, יש להתייחס לקוד הנמצא בכתובת משתנה. במילים אחרות יש להשתמש במושג של מצביע לפונקציה.

הקוד הבא מדגים איך אפשר לממש פולימורפיזם בשפת C, שפה שלא תומכת בפולימורפיזם באופן מובנה:

 #include <malloc.h> 
 #include <stdio.h> 
 
 
 typedef void (*fun_t)(void);   
 
 typedef struct Car {  
   fun_t stop; 
   /* fun_t placeJack, lift, ... */ 
 } Car; 
 
 Car* createCar(fun_t stopFunction) {/*fun_t placeJackFunction, fun_t liftFunction,...*/
   Car *p = (Car*)malloc(sizeof(Car)); 
   p->stop = stopFunction;
   /* p->placeJack = placeJackFunction; p->lift = ... */
   return p; 
  }
 
 void busStop() { printf("Stopping the bus...\n"); }
 /* void busPlaceJack() {...} void busLift() {...} ... */
 Car* createBus() { return createCar(busStop); } 
 
 void privateStop() { printf("Stopping the private car...\n"); }
 /* void privatePlaceJack() {...} void privateLift() {...} ... */
 Car* createPrivate() { return createCar(privateStop); } 
 
 void changeWheel(Car *car) {
   car->stop(); 
   /* car->placeJack(); car->lift();... */
 }
 
 int main() {
   Car *p1 = createBus(), *p2 = createPrivate();
   changeWheel(p1);
   changeWheel(p2);
   /* free memory .. */ 
   return 0; 
 }

הדוגמה האחרונה פשטנית במקצת. היא מתחמקת מבעיות טכניות שונות המופיעות באובייקטים פחות מנוונים מאלה שבדוגמה. בנוסף, ניתן לראות שהשיטה המוצגת בדוגמה, בזבזנית בזיכרון. עבור כל אובייקט (מכונית) יש לשמור מספר מצביעים לפונקציות כמספר הפונקציות שיש למכונית. אותם מצביעים לפונקציות יכולים להוות את רוב הזיכרון הדרוש לאיכסון האובייקט. בזבוז הזיכרון נובע מהעובדה, שאוסף הפונקציות עליהם מצביע האובייקט הוא מאפיין של ה - class ולא של האובייקט הספציפי. לדוגמה, לכל האובייקטים מסוג Bus יהיו בדיוק אותם ערכים בכל מצביעי הפונקציות שלהם.

בגלל העובדה שמדובר בעצם במידע של ה-class, הגיוני לצמצם את כל מצביעי הפונקציות למצביע יחיד שיפנה למקום בו נמצאת כל האינפורמציה של ה-class. האינפורמציה הזו יכולה להיות פשוט מערך של מצביעים לפונקציות - אותם מצביעים שתוארו בדוגמה והוו שדות באובייקט. הרעיון שתואר הוא באמת השיטה המקובלת לממש פולימורפיזם של זמן ריצה. אותו מערך פונקציות נקרא virtual table ואותו שדה יחיד המצביע עליה נקרא virtual table pointer.

Virtual table.png

כפי שניתן לראות בתמונה, כל אובייקט מסוג Car או מסוג היורש מ-Car, מחזיק מצביע לטבלה ייעודית לאותו סוג. הטבלה מחזיקה מצביעים לפונקציות. הקוד

 p1.placeJack()

יתורגם לקוד הדומה לקוד הבא:

 p1.m_vtbl_ptr[2]()

כפי שניתן לראות, קיימת כאן הסתמכות על העובדה שהפונקציה placeJack נמצאת תמיד באותו אינדקס, בכל הטבלאות הווירטואליות (במקרה זה - 2).

[עריכה] מחיר פולימורפיזם הממומש על ידי virtual table

מבחינת זיכרון, כאשר ל-Class יש לפחות פונקציה פולימורפית (וירטואלית) אחת, כל אובייקט מסוגו (וכמובן מסוג יורשיו) יכיל מצביע virtual table pointer. עבור אובייקטים גדולים הדבר עשוי להיות זניח אבל עבור אובייקטים קטנים, במיוחד אם יש מופעים רבים שלהם, הדבר עלול להיות משמעותי.

מבחינת זמן הריצה המחיר הוא מעבר אחד דרך תא של מערך הטבלה הווירטואלית. בדרך כלל הדבר מתורגם לפקודות בודדות בשפת מכונה (במקרים רבים - פקודה בודדת). לרוב, התשלום בזמן הריצה הוא זניח אבל במקרים בהם הפונקציה הווירטואלית קצרה מאוד והיא נקראת מספר רב של פעמים - המחיר עלול להיות משמעותי.

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

[עריכה] קישורים חיצוניים

  • הרצאה על פולימורפיזם במסגרת קורס שניתן באוניברסיטה העברית.

[עריכה] לקריאה נוספת

  • John C. Mitchell, Concepts In Programming Languages, Cambridge University Press, 2003 פרק 6
  • David A. Watt, Programming Language Concepts and Paradigms, פרק 7
כלים אישיים
גרסאות שפה
מרחבי שם
פעולות
ניווט
קהילה
תיבת כלים
דף זה בשפות אחרות
הדפסה/יצוא