简体   繁体   English

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

[英]Override child class inherited property with more derived type

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
}

This obviously doesn't work as teeth must be same type as in the Animal class to be overriden in the Mouse class.这显然不起作用,因为牙齿必须与 Animal 类中的类型相同才能在 Mouse 类中覆盖。 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?但是,如果允许我在从 Animal 继承的任何函数中使用派生程度更高的类型,这样的事情是否可以实现? For example if the Animal class contained a function to bite:例如,如果 Animal 类包含一个咬的函数:

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

I could call the Bite() function inherited from Animal and it would use the Mouse class' field of type SmallTeeth .我可以调用从 Animal 继承的Bite()函数,它会使用类型为SmallTeeth的 Mouse 类的字段。 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?如果不是,那么解决这个问题的正确方法是什么?

NOTE: This answer was written in 2016. Return type covariance has (amazingly!) been added to C# in the years since.注意:这个答案是在 2016 年写的。从那以后的几年里,返回类型协方差已经(惊人地!)被添加到 C# 中。 Keep that in mind when reading this answer.阅读此答案时请记住这一点。


The feature you want is called return type covariance , and C# does not support it.你想要的特性叫做return type covariance ,C# 不支持。 (C++ does, incidentally.) (顺便说一句,C++ 确实如此。)

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.通过使派生类对它可以接受的内容进行更多限制,您违反了基类的约定。

So don't do that.所以不要那样做。

There are a bunch of ways though that you can achieve what you want in C#.有很多方法可以在 C# 中实现你想要的。

Here's just one of them:这里只是其中之一:

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; } }
}

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.现在,如果您将鼠标投射到 IAnimal,您将获得返回 Teeth 的属性,如果您正常使用鼠标,您将获得返回 SmallTeeth 的属性。

I describe another way to solve this problem here:我在这里描述了解决这个问题的另一种方法:

Does C# support return type covariance? C# 是否支持返回类型协方差?

And the generic solution given in the other answer also works, though personally I prefer to keep generics out of it unless necessary.另一个答案中给出的通用解决方案也有效,尽管我个人更喜欢将泛型排除在外,除非有必要。

Do a search on "return type covariance in C#" for more information on this pattern.搜索“C# 中的返回类型协方差”以获取有关此模式的更多信息。

Actually yes.其实,是。 You could but should not use generics for that purpose including a type constraint ( see comments below and the post of Eric Lippert who explains in detail, what you are wanting or trying to achieve in your situation):可以不应该为此目的使用generics ,包括类型约束(请参阅下面评论Eric Lippert 的帖子,他详细解释了您在您的情况下想要或试图实现的目标):

public class Animal<T>  where T : Teeth
{
    public virtual T teeth {get;set;}
}

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM