פורסם 2007 בפברואר 218 שנים בגדול, השאלה שלי היא כזו:יש לי זוג קלאסים, Base ו-Derived, כאשר Derived יורש מ-Base.הבעיה היא ש-ICollection<Derived> אינו יורש מ-ICollection<Base>.האם יש דרך פשוטה לבצע המרה מ-ICollection<Derived> ל-ICollection<Base>?קצת יותר פירוט:יש לי מודול שבו מוגדרים כמה קלאסים - קלאס אב (נקרא לו BaseClass), ושני קלאסים (נקרא להם A ו-B) שיורשים ממנו.איפשהו במודול יש לי זוג פונקציות, אחת מחזירה ICollection<A> (נקרא לה getA לנוחות) והשנייה מחזירה ICollection<B> (נקרא לה getB).במודול אחר, שמשתמש במודול הנ"ל, הגדרתי קלאס (נקרא לו C) שיש לו פונקציה וירטואלית שמחזירה ICollection<BaseClass>.אני רוצה להגדיר שני קלאסים שיורשים מהקלאס הזה וממשים את הפונקציה הזו, כאשר הראשון משתמש ב-getA והשני משתמש ב-getB.הבעיה היא ש-getA ו-getB לא מחזירות ICollection<BaseClass>, ולכן הקומפיילר מסרב לקמפל.(אם זה לא מספיק מובן אני יכול לצרף קוד לדוגמה)חשבתי כבר על שני פתרונות אפשריים:1. להגדיר קלאס גנרי משלי שיעטוף את ICollection<BaseClass>, ויבצע את ההמרות מ-BaseClass ל-A או B ולהיפך.2. להגדיר את C שיהיה גנרי על ה-BaseClass, ואז הקלאסים שיורשים ממנו ירשו בעצם מ-C<A> ו-C<B>.שני הפתרונות לא ממש יפים...יש למישהו פתרון יותר טוב?
פורסם 2007 בפברואר 218 שנים מחבר את הקוד עצמו אני לא יכול לצרף, אבל זה קוד לדוגמה.המודול הראשון שדיברתי עליו הוא זה:public abstract class Base{ // some code}public class A : Base{ // some code}public class B : Base{ // some code}public class SomeOtherClass{ public ICollection<A> getA() { // some code which returns ICollection<A> } public ICollection<B> getB() { // some code which returns ICollection<B> }}מבחינתי המודול הזה קבוע ואני לא יכול לשנות אותו.המודול שאני רוצה לכתוב הוא כזה:public abstract class BaseProvider{ public abstract ICollection<Base> getCollection();}public class AProvider : BaseProvider{ public override ICollection<Base> getCollection() { SomeOtherClass x = new SomeOtherClass(); return x.getA(); // ERROR! can't cast ICollection<A> to ICollection<Base> }}public class BProvider : BaseProvider{ public override ICollection<Base> getCollection() { SomeOtherClass x = new SomeOtherClass(); return x.getB(); // ERROR! can't cast ICollection<B> to ICollection<Base> }}אני מקווה שזה מספיק מובן.תודה!
פורסם 2007 בפברואר 218 שנים את A ו- B אתה מכיר מהמודול החיצוני?אם כן - נראה לי שאתה יכול להגדיר את getCollection כפונקציה שלוקחת פרמטר template של ה- class שאותו אתה רוצה לקבל (ואז אתה יכול גם להגדיר אותה עם specialization ל- A ו- B מבלי ממש ליצור שני classes ל- AProvider ו- BProvider)
פורסם 2007 בפברואר 218 שנים אני חושב שה- Base Class שלך פשוט צריך לממש ממשק (Interface באנגלית) כך שה-קלאס הלקוח שלך עובד עם ממשק זה ולא משנה לו אם בנקודה מסויימת הוא מפעיל מתודה של קלאס A או קלאס B (שיורשים את קלאס האב)
פורסם 2007 בפברואר 218 שנים מחבר בומרנג - אני יודע שאני יכול (זו וריאציה על אחת מהאופציות שרשמתי בפוסט הראשון), רציתי לדעת אם יש דרך להימנע מזה.NJorl - לאיזה Base Class התכוונת? זה שקראתי לו Base (במודול הראשון) או זה שקראתי לו BaseProvider (במודול השני)?אני לא יכול לשנות את המודול הראשון (טכנית כן, כי גם אני כתבתי אותו, אבל אני כבול ל-design הספציפי הזה).
פורסם 2007 בפברואר 218 שנים זה קצת יותר מוצלח מהאופציה הראשונה, כי הכל נעשה ב- compile-time, אז אין לך באמת בעיה של המרות.
פורסם 2007 בפברואר 218 שנים ה- base ש- A ו- B יורשים ממנו כך אתה משיג פולימורפיזם , כל קלאס מכיל את אותן שיטות שה- base דורש מ- A ו- B לממש כ- interfaceאבל A ו-B יכולים לממש את אותן שיטות בצורה שונה העיקר שיהיו ממומשות
ארכיון
דיון זה הועבר לארכיון ולא ניתן להוסיף בו תגובות חדשות.