31

我有以下界面:

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

通过针对接口进行编程,我可以做我需要做的事情,但我实际上不能将 Object 强制转换为 IRelativeTo 所以我可以使用它。

这是一个微不足道的例子,但我希望它能阐明我想要做什么。

4

3 回答 3

27

如果我理解这个问题,那么最常见的方法是声明一个非泛型基接口,即

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);

这两种方法都有好处。

于 2008-10-21T16:03:38.750 回答
13

不幸的是,继承不适用于泛型。如果您的函数需要 IRelativeTo,您也可以将函数设为通用:

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

如果我没记错的话,当你使用上面的函数时,你甚至不需要指定类型,编译器应该根据你提供的参数来计算它。

如果您想在类或方法中保留对这些 IRelativeTo 对象之一的引用(并且您不在乎 T 是什么),则需要再次使此类/方法通用。

我同意,这有点痛苦。

于 2008-10-21T16:02:56.210 回答
7

如果您只关心 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);
于 2008-10-21T16:32:02.983 回答