我有一些继承问题,因为我有一组相互关联的抽象类,需要全部重写以创建客户端实现.理想情况下,我想做类似以下的事情:
abstract class Animal { public Leg GetLeg() {...} } abstract class Leg { } class Dog : Animal { public override DogLeg Leg() {...} } class DogLeg : Leg { }
这将允许任何使用Dog类的人自动获取DogLegs以及任何使用Animal类获取Legs的人.问题是被覆盖的函数必须与基类具有相同的类型,因此不会编译.我不明白为什么它不应该,因为DogLeg可以隐式地施放到Leg.我知道有很多方法可以解决这个问题,但我更好奇为什么在C#中无法实现/实现这一点.
编辑:我有点修改,因为我实际上在我的代码中使用属性而不是函数.
编辑:我将其更改回函数,因为答案仅适用于那种情况(属性的set函数的value参数的协方差不应该起作用).对不起波动!我意识到这使得许多答案看起来无关紧要.
简短的回答是GetLeg的返回类型是不变的.可以在这里找到答案很长的答案:协方差和逆变
我想补充一点,虽然继承通常是大多数开发人员从他们的工具箱中取出的第一个抽象工具,但几乎总是可以使用组合.对于API开发人员来说,组合工作稍微多一些,但是使API对其消费者更有用.
很明显,如果你在破损的DogLeg上操作,你需要一个演员表.
狗应该返回Leg而不是DogLeg作为返回类型.实际的课程可能是DogLeg,但重点是解耦,所以Dog的用户不必了解DogLegs,他们只需要了解Legs.
更改:
class Dog : Animal { public override DogLeg GetLeg() {...} }
至:
class Dog : Animal { public override Leg GetLeg() {...} }
不要这样做:
if(a instanceof Dog){ DogLeg dl = (DogLeg)a.GetLeg();
它违背了编程为抽象类型的目的.
隐藏DogLeg的原因是因为抽象类中的GetLeg函数返回一个抽象的Leg.如果你要覆盖GetLeg,你必须返回一条腿.这就是在抽象类中使用方法的重点.将该方法传播给它的孩子们.如果您希望Dog的用户了解DogLegs,请创建一个名为GetDogLeg的方法并返回DogLeg.
如果您可以像提问者那样做,那么Animal的每个用户都需要了解所有动物.