עבור לתוכן

שילוב של ירושה ו-Generic ב-.NET

Featured Replies

פורסם

בגדול, השאלה שלי היא כזו:

יש לי זוג קלאסים, 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>.

שני הפתרונות לא ממש יפים...

יש למישהו פתרון יותר טוב?

פורסם

לא ממש הבנתי לעומק את הבעיה שלך.

אם תוכל לצרף את הקוד זה יעזור

פורסם
  • מחבר

את הקוד עצמו אני לא יכול לצרף, אבל זה קוד לדוגמה.

המודול הראשון שדיברתי עליו הוא זה:

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>
}
}

אני מקווה שזה מספיק מובן.

תודה!

פורסם

את A ו- B אתה מכיר מהמודול החיצוני?

אם כן - נראה לי שאתה יכול להגדיר את getCollection כפונקציה שלוקחת פרמטר template של ה- class שאותו אתה רוצה לקבל (ואז אתה יכול גם להגדיר אותה עם specialization ל- A ו- B מבלי ממש ליצור שני classes ל- AProvider ו- BProvider)

פורסם

אני חושב שה- Base Class שלך פשוט צריך לממש ממשק (Interface באנגלית)

כך שה-קלאס הלקוח שלך עובד עם ממשק זה ולא משנה לו אם בנקודה מסויימת הוא מפעיל מתודה של קלאס A או קלאס B (שיורשים את קלאס האב)

פורסם
  • מחבר

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

NJorl - לאיזה Base Class התכוונת? זה שקראתי לו Base (במודול הראשון) או זה שקראתי לו BaseProvider (במודול השני)?

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

פורסם

זה קצת יותר מוצלח מהאופציה הראשונה, כי הכל נעשה ב- compile-time, אז אין לך באמת בעיה של המרות.

פורסם

ה- base ש- A ו- B יורשים ממנו כך אתה משיג פולימורפיזם , כל קלאס מכיל את אותן שיטות שה- base דורש מ- A ו- B לממש כ- interface

אבל A ו-B יכולים לממש את אותן שיטות בצורה שונה העיקר שיהיו ממומשות

ארכיון

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

דיונים חדשים