שילוב של ירושה ו-Generic ב-.NET - תכנות - HWzone פורומים
עבור לתוכן
  • צור חשבון

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


שניצל

Recommended Posts

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

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

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

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

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

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

ארכיון

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

×
  • צור חדש...