用更多派生类型重写子类继承的属性 [英] Override child class inherited property with more derived type

查看:98
本文介绍了用更多派生类型重写子类继承的属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要实现的目标的简化示例如下:

A simplified example of what i'm trying to achieve looks like this:

public class Animal
{
    public virtual Teeth teeth {get;set;}
}

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

这显然不起作用,因为牙齿必须与Animal类中的牙齿类型相同才能在Mouse类中覆盖.但是,是否可以实现这样的事情,使我可以在从Animal继承的任何函数中使用更多派生类型?例如,如果Animal类包含要咬的函数:

This obviously doesn't work as teeth must be same type as in the Animal class to be overriden in the Mouse class. But can something like this be achieved where I would be allowed to use the more derived type in any functions that are inherited from Animal? For example if the Animal class contained a function to bite:

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

我可以调用从Animal继承的Bite()函数,它将使用类型为SmallTeeth的Mouse class'字段.这可能吗?这是做我想做的最好的方法吗?如果没有,那么解决该问题的正确方法是什么?

I could call the Bite() function inherited from Animal and it would use the Mouse class' field of type SmallTeeth. Is this possible? and is it the best way to do what i'm trying to do? If not, what would be the correct approach to this problem?

推荐答案

所需的功能称为返回类型协方差,而C#不支持. (顺便说一句,C ++确实如此.)

The feature you want is called return type covariance, and C# does not support it. (C++ does, incidentally.)

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

The usual case made for covariant return types is:

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

这是不合法的,但是如果合法,那将是安全.就是说,如果您手头有一只动物,而您想要一只笼子,即使它是一条鱼,您也会得到一只.为什么?因为水族馆是一种笼子.

This is not legal, but if it were legal it would be safe. That is, if you have an Animal in hand and you ask for a cage, you get one, even if it is a fish. Why? Because an aquarium is a kind of cage.

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

What you propose though is not only illegal, it's unsafe:

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

合同规定,可以用任何一种牙齿来呼叫二传手.通过使派生类对其接受的内容更严格地限制,就违反了基类的约定.

The contract is that the setter can be called with any kind of tooth. By making the derived class more restrictive in what it can accept, you violate the contract of the base class.

所以不要那样做.

尽管有很多方法可以实现C#所需的功能.

There are a bunch of ways though that you can achieve what you want in 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的属性.

Now if you cast a mouse to IAnimal you get the property that returns Teeth, and if you use a mouse normally you get the property that returns SmallTeeth.

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

I describe another way to solve this problem here:

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

另一个答案中给出的通用解决方案也可以使用,尽管我个人更喜欢除非需要将通用排除在外.

And the generic solution given in the other answer also works, though personally I prefer to keep generics out of it unless necessary.

搜索"C#中的返回类型协方差"以获取有关此模式的更多信息.

Do a search on "return type covariance in C#" for more information on this pattern.

这篇关于用更多派生类型重写子类继承的属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆