מה ההבדלים בין virtual ל new בהעמסת מתודות - תכנות - HWzone פורומים
עבור לתוכן
  • צור חשבון

מה ההבדלים בין virtual ל new בהעמסת מתודות


bdoron

Recommended Posts

הבנתי כי כאשר אני רוצה לממש פולימורפיזים אני יכול לעשות זאת ב2 צורות

צורה ראשונה, דרך השימוש במילה השמורה virtual ואז כל פעם שאני רוצה לעשות override אני רושם override בפונקציה תחת אותו עץ

ואני יכול לעשות זאת על ידי השימוש במילה new

השאלה שלי היא מתי אני בוחר להשתמש בnew ומתי אני אבחר להשתמש בvirtual

אשמח להסבר קליל בסי שארפ :)

קישור לתוכן
שתף באתרים אחרים

בשתי מילים: override היא פולימורפית, new היא לא פולימורפית.

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

נניח שמחלקה A מגדירה פונקציה וירטואלית בשם f שמדפיסה "A", ומחלקה B יורשת מ-A וגם מגדירה פונקציה בשם f שמדפיסה "B". כיוון ש-f וירטואלית, זה מחייב את B להגדיר אותה באמצעות override או באמצעות new.

נסתכל על הקוד הבא:

A x = new B();
x.f();

השאלה - מה יודפס, "A" או "B"? התשובה תלויה באיך f מוגדרת ב-B.

אם f מוגדרת ב-B ע"י override, אז יש פה פולימורפיזם כמו שאתה מכיר - הפונקציה שתיקרא היא זו של B, ולכן יודפס "B". אם f מוגדרת ע"י new, אז הפונקציה f שב-B לא קשורה לפונקציה f שב-A, ולכן מה שיודפס הוא הפונקציה f של A, כלומר יודפס "A".

על מנת לקרוא לפונקציה f של B, צריך שהטיפוס של x יהיה ממש B, דהיינו:

B x = new B();
x.f();

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

קישור לתוכן
שתף באתרים אחרים

לא תמיד - יש מקרים (נדירים) שבהם אתה לא רוצה (או לא יכול), כמו בדוגמה שנתתי בהודעה הקודמת.

עוד דוגמה (לפי הדוגמה שכאן http://msdn.microsoft.com/en-us/library/6fawty39.aspx):

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

בקוד שלך יש מחלקה בשם B שיורשת מ-A, ומגדירה פונקציה משלה בשם f (אין פונקציה בשם הזה ב-A).

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

קישור לתוכן
שתף באתרים אחרים

ארכיון

דיון זה הועבר לארכיון ולא ניתן להוסיף בו תגובות חדשות.

×
  • צור חדש...