我想要实现的简化示例如下所示:
public class Animal
{
public virtual Teeth teeth {get;set;}
}
public class Mouse : Animal
{
public override SmallTeeth teeth {get; set;} // SmallTeeth Inherits from Teeth
}
Run Code Online (Sandbox Code Playgroud)
这显然不起作用,因为牙齿必须与要在Mouse类中重写的Animal类中的类型相同.但是,在允许在从Animal继承的任何函数中使用更多派生类型的情况下,可以实现这样的事情吗?例如,如果Animal类包含一个咬合函数:
public void Bite()
{
teeth.bite()
Console.WriteLine("Ouch")
}
Run Code Online (Sandbox Code Playgroud)
我可以调用Bite()从Animal继承的函数,它将使用Mouse类的字段类型SmallTeeth.这可能吗?这是我做我想做的最好的方式吗?如果没有,这个问题的正确方法是什么?
Eri*_*ert 14
您想要的功能称为返回类型协方差,C#不支持它.(顺便说一句,C++确实如此.)
协变返回类型的常见情况是:
abstract class Animal
{
public abstract Cage GetCage();
}
public class Fish : Animal
{
public override Aquarium GetCage() { ... }
}
Run Code Online (Sandbox Code Playgroud)
这不合法,但如果它是合法的,那将是安全的.也就是说,如果你手中有一只动物,并且你要求一只笼子,即使它是一条鱼,你也会得到它.为什么?因为水族馆是一种笼子.
你提出的建议不仅非法,而且不安全:
Animal animal = new Mouse();
animal.Teeth = new TRexTeeth();
Run Code Online (Sandbox Code Playgroud)
合同是可以用任何种类的牙齿来召唤制定者.通过使派生类在它可以接受的内容中更具限制性,您违反了基类的契约.
所以不要这样做.
有很多方法可以让你在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; } }
}
Run Code Online (Sandbox Code Playgroud)
现在,如果您将鼠标转换为IAnimal,则会获得返回Teeth的属性,如果您通常使用鼠标,则会获得返回SmallTeeth的属性.
我在这里描述了另一种解决这个问题的方法:
另一个答案中给出的通用解决方案也有效,但我个人更喜欢将泛型保留在其中,除非必要.
有关此模式的更多信息,请搜索"C#中的返回类型协方差".