这个问题很混乱。让我看看我能不能澄清一下。
当我尝试实现IGreatInterface 时,编译器将aMethodBeta() 标记为错误,因为我使用IAnInterface 的子类型创建了该方法,我想像这样实现该方法:Object aMethodBeta(AnInterestingClass parameter)。
这是不合法的。稍微简化一下:
class Food {}
class Fruit : Food {}
class Meat : Food {}
interface IEater
{
void Eat(Food food);
}
class Vegetarian : IEater
{
public void Eat(Fruit fruit);
}
Vegetarian 类不履行IEater 的合同。您应该能够传递 any Food to Eat,但 Vegetarian 只接受 Fruit。 C# 不支持虚方法形参协方差,因为那不是类型安全的。
现在,你可能会说,这个怎么样:
interface IFruitEater
{
void Eat(Fruit fruit);
}
class Omnivore : IFruitEater
{
public void Eat(Food food);
}
现在我们有了类型安全; Omnivore 可以用作IFruitEater,因为Omnivore 可以吃水果以及任何其他食物。
不幸的是,C# 不支持 虚方法形式参数类型逆变,尽管这样做在理论上是类型安全的。很少有语言支持这一点。
同样,C# 也不支持虚方法返回类型变化。
我不确定这是否真的回答了您的问题。你能澄清一下这个问题吗?
更新:
怎么样:
interface IEater
{
void Eat<T>(T t) where T : Food;
}
class Vegetarian : IEater
{
// I only want to eat fruit!
public void Eat<Fruit>(Fruit food) { }
}
不,这也不合法。 IEater 的约定是您将提供一个方法Eat<T>,它可以采用任何T,即Food。你不能部分地执行合同,就像你不能这样做一样:
interface IAdder
{
int Add(int x, int y);
}
class Adder : IAdder
{
// I only know how to add two!
public int Add(2, int y){ ... }
}
但是,您可以这样做:
interface IEater<T> where T : Food
{
void Eat(T t);
}
class Vegetarian : IEater<Fruit>
{
public void Eat(Fruit fruit) { }
}
这是完全合法的。但是,您不能这样做:
interface IEater<T> where T : Food
{
void Eat(T t);
}
class Omnivore : IEater<Fruit>
{
public void Eat(Food food) { }
}
再次因为,C# 不支持虚方法形式参数逆变或协方差。
请注意,C#是否支持参数多态协方差,因为这样做是已知的类型安全的。例如,这是合法的:
IEnumerable<Fruit> fruit = whatever;
IEnumerable<Food> food = fruit;
一个水果序列可以用作一个食物序列。或者,
IComparable<Fruit> fruitComparer = whatever;
IComparable<Apples> appleComparer = fruitComparer;
如果你有可以比较任意两个水果的东西,那么它就可以比较任意两个苹果。
然而,这种协变和逆变只有在满足以下所有条件时才是合法的:(1) 变体可证明是类型安全的,(2) 类型的作者添加了变体注释,表明所需的协变和反变差异,(3) 涉及的不同类型参数都是引用类型,(4) 泛型类型是委托或接口。