使用更多派生类型覆盖子类inheritance的属性

我想要实现的简化示例如下所示:

public class Animal { public virtual Teeth teeth {get;set;} } public class Mouse : Animal { public override SmallTeeth teeth {get; set;} // SmallTeeth Inherits from Teeth } 

这显然不起作用,因为牙齿必须与要在Mouse类中重写的Animal类中的相同类型。 但是,在允许在从Animalinheritance的任何函数中使用更多派生类型的情况下,可以实现这样的事情吗? 例如,如果Animal类包含一个咬合函数:

 public void Bite() { teeth.bite() Console.WriteLine("Ouch") } 

我可以调用inheritance自Animal的Bite()函数,它将使用SmallTeeth类型的Mouse类’字段。 这可能吗? 这是我做我想做的最好的方式吗? 如果没有,这个问题的正确方法是什么?

您想要的function称为返回类型协方差 ,C#不支持它。 (顺便说一句,C ++确实如此。)

协变返回类型的常见情况是:

 abstract class Animal { public abstract Cage GetCage(); } public class Fish : Animal { public override Aquarium GetCage() { ... } } 

这不合法,但如果它是合法的,那将是安全的 。 也就是说,如果你手中有一只动物并且你要求一只笼子,即使它是一条鱼,你也会得到它。 为什么? 因为水族馆是一种笼子。

你提出的建议不仅非法,而且不安全:

 Animal animal = new Mouse(); animal.Teeth = new TRexTeeth(); 

合同是可以用任何种类的牙齿调用定位器。 通过使派生类在其可接受的内容中更具限制性,您违反了基类的合同。

所以不要这样做。

有很多方法可以让你在C#中实现你想要的东西。

这只是其中之一:

 interface IAnimal { Teeth Teeth { get; } // READ ONLY } class Mouse : IAnimal { private SmallTeeth smallTeeth; public SmallTeeth Teeth { get { return smallTeeth; } } Teeth IAnimal.Teeth { get { return this.Teeth; } } } 

现在,如果您将鼠标转换为IAnimal,则会获得返回Teeth的属性,如果您通常使用鼠标,则会获得返回SmallTeeth的属性。

我在这里描述了另一种解决这个问题的方法:

C#是否支持返回类型协方差?

另一个答案中给出的通用解决方案也有效,但我个人更喜欢将generics保留在其中,除非必要。

有关此模式的更多信息,请搜索“C#中的返回类型协方差”。

其实,是。 您可以不应该为此目的使用generics ,包括类型约束( 请参阅下面 注释以及Eric Lippert的post,他详细解释了您在您的情况下想要或想要实现的目标):

 public class Animal where T : Teeth { public virtual T teeth {get;set;} } public class Mouse : Animal { public override SmallTeeth teeth {get; set;} // SmallTeeth Inherits from Teeth }