我有以下界面:
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,所以我可以使用它。
这是一个微不足道的例子,但我希望它能澄清我想要做的事情。
答案 0 :(得分:22)
如果我理解这个问题,那么最常见的方法是声明一个非通用的基本接口,即
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()
的参数,那么通常你不需要自己指定泛型类型参数 - 编译器会推断它 - 即< / p>
DoSomething(foo);
而不是
DoSomething<SomeType>(foo);
这两种方法都有好处。
答案 1 :(得分:11)
遗憾的是,继承不适用于泛型。如果你的函数需要IRelativeTo,你也可以使函数通用:
void MyFunction<T>(IRelativeTo<T> sth) where T : IObject
{}
如果我没记错的话,当你使用上面的函数时,甚至不需要指定类型,编译器应该根据你提供的参数找出它。
如果你想在类或方法中保留对这些IRelativeTo对象之一的引用(你不关心T是什么),你需要再次使这个类/方法通用。
我同意,这有点痛苦。
答案 2 :(得分:5)
如果您关心的是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);