سؤال

ولدي واجهة التالية:

internal interface IRelativeTo<T> where T : IObject
{
    T getRelativeTo();
    void setRelativeTo(T relativeTo);
}

ووحفنة من الفئات التي (يجب) تنفيذه، مثل:

public class AdminRateShift : IObject, IRelativeTo<AdminRateShift>
{
    AdminRateShift getRelativeTo();
    void setRelativeTo(AdminRateShift shift);
}

وأنا أدرك أن هؤلاء الثلاثة ليست هي نفسها:

IRelativeTo<>
IRelativeTo<AdminRateShift>
IRelativeTo<IObject>

ولكن على الرغم من ذلك، وأنا بحاجة إلى وسيلة للعمل مع جميع فئات مختلفة مثل AdminRateShift (وFXRateShift، DetRateShift) التي ينبغي أن تنفذ جميع IRelativeTo. دعنا نقول لدي وظيفة والتي ترجع AdminRateShift ككائن:

IRelativeTo<IObject> = getObjectThatImplementsRelativeTo(); // returns Object

وبواسطة البرمجة ضد واجهة، وأستطيع أن أفعل ما أريد، ولكن أنا لا يمكن أن يلقي في الواقع كائن إلى IRelativeTo حتى أتمكن من استخدامها.

وانها مثال تافهة، ولكن آمل أن توضيح ما أحاول القيام به.

هل كانت مفيدة؟

المحلول

إذا فهمت السؤال، ثم النهج الأكثر شيوعا سيكون لإعلان غير الجنيسة قاعدة واجهة، أي بمعنى.

internal interface IRelativeTo
{
    object getRelativeTo(); // or maybe something else non-generic
    void setRelativeTo(object relativeTo);
}
internal interface IRelativeTo<T> : IRelativeTo
    where T : IObject
{
    new T getRelativeTo();
    new void setRelativeTo(T relativeTo);
}

وثمة خيار آخر هو بالنسبة لك لرمز إلى حد كبير في الأدوية ... أي أن يكون لديك طرق مثل

void DoSomething<T>() where T : IObject
{
    IRelativeTo<IObject> foo = // etc
}

وإذا كان IRelativeTo<T> حجة لDoSomething()، ثم <م> عادة لا تحتاج إلى تحديد نوع الوسيطة العامة نفسك - والمترجم الاستدلال عليه - أي بمعنى

DoSomething(foo);

وليس

DoSomething<SomeType>(foo);

وهناك فوائد لكلا النهجين.

نصائح أخرى

للأسف الميراث لا يعمل مع الأدوية. إذا تتوقع الدالة IRelativeTo، يمكنك جعل وظيفة عمومية أيضا:

void MyFunction<T>(IRelativeTo<T> sth) where T : IObject
{}

إذا كنت أتذكر بشكل صحيح، عند استخدام وظيفة فوق لا تحتاج حتى لتحديد نوع، المترجم يجب أن الرقم بها على أساس الحجة التي قمت بإرسالها.

إذا كنت تريد أن تبقي إشارة إلى واحد من هذه الكائنات IRelativeTo داخل فئة أو طريقة (وأنت لا يهمني ما هو T ذلك)، تحتاج إلى جعل هذه الطبقة / طريقة عام مرة أخرى.

وأنا أتفق، فمن قليلا من الألم.

وإذا كان كل ما يهمني هو أن صفقات IRelativeTo مع IObjects فإنك لا تحتاج لجعله عام:

interface IRelativeTo
 {
   IObject getRelativeTo();
   void setRelativeTo(IObject relativeTo)
 }

ويمكن أن تكون الفصول تنفيذ تزال عام، ولكن:

abstract class RelativeTo<T>  : IRelativeTo where T : IObject
 {  
   public virtual T getRelativeTo() {return default(T);}

   public virtual void setRelativeTo(T relativeTo) {}

   IObject IRelativeTo.getRelativeTo() {return this.getRelativeTo(); }

   void IRelativeTo.setRelativeTo(IObject relativeTo) 
    { this.setRelativeTo((T) relativeTo);
    }
 }

class AdminRateShift :  RelativeTo<AdminRateShift>, IObject {}

وبعد ذلك يمكنك القيام بذلك:

  IRelativeTo irt = new AdminRateShift();
  IObject o = irt.getRelativeTo();
  irt.setRelativeTo(o);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top