子类作为返回类型的泛型重写方法 [英] Generic overridden method with subclass as return type

查看:45
本文介绍了子类作为返回类型的泛型重写方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个基类Animal.

Let's say that i have a base class Animal.

public abstract class Animal;

此动物类具有抽象方法:

This animal class has the abstract method:

public abstract T Copy<T>() where T : Animal

在Lion类中重写此方法时:

When this method is overridden in the Lion class:

public class Lion : Animal
{
    string roar = "Roar";
}

我希望退回这只狮子的副本,但不提供参考.所以我认为应该这样重写:

i wish to return a copy of this lion without its references. So what i think it should be overridden like is this:

public abstract T Copy<T>()
{
    return new Lion(){ 
        roar = this.roar;
    }
}

但这是不允许的,因为Lion不能转换为T型(动物).

but this is not allowed, because Lion cannot be converted to the T type(which is an Animal).

这是一个可以理解的错误,因为并非每个动物都一定是狮子.

This is a understandable error, becouse not every Animal is necessarily a Lion.

但是在复制方法知道它应该返回子类Lion的情况下,又如何不必强制将所有类型转换为正确的类型,我又如何设置这种情况呢?而且仍然让每个动物都有一个Copy()方法.

But how can i set this situation up where the copy method knows it supposed to return the subclass, Lion in this case, and not have to do all kinds of casting to the correct type? And still have every animal have a method Copy().

推荐答案

在这种情况下,您不能使用泛型,因为它们不支持您想做的事情.

You can not use generics in this situation, they don't support what you want to do.

但是,如果您使用的是C#9,则可以使用新的协变量返回类型"支持.

However, if you're on C# 9 you can use the new "Covariant return types" support.

具体来说,您可以这样编写代码:

Specifically, you can write your code like this:

public abstract class Animal
{
    public abstract Animal Copy();
}

public class Lion : Animal
{
    public override Lion Copy() => new Lion();
    //               ^
    //  notice that I used Lion here, not Animal
}

如果您通过声明为 Animal 类型的引用调用 Copy ,但引用了 Lion 的实例,则将返回键入 Animal (动物)的值,其中包含 Lion (狮子)参考.

If you're calling Copy through a reference declared as being of type Animal but referencing an instance of Lion, you will get back a value typed to Animal, holding a Lion reference.

但是,如果您通过引用为 Lion 的引用来调用 Copy ,那么您也将返回引用为 Lion 的引用

However, if you're calling Copy through a reference typed to Lion, you will get back a reference typed to Lion as well.

示例:

Animal a = new Lion();
Animal c = a.Copy(); <-- holding a Lion, but type is Animal

Lion l = new Lion();
Lion l2 = l.Copy();  <-- type is now Lion as well

如果您不在C#9上,那么另一种选择是通过使Animal通用,使Copy方法知道派生类的类型:

If you're not on C# 9, a different option would be to make the Copy method know the type of the derived class, by making Animal generic:

void Main()
{
    Animal<Lion> a = new Lion();
    Lion c1 = a.Copy(); // <-- notice that this is now typed to Lion as well
    
    Lion l = new Lion();
    Lion c2 = l.Copy();
}

public abstract class Animal<T> where T : Animal<T>
{
    public abstract T Copy();
}

public class Lion : Animal<Lion>
{
    public override Lion Copy() => new Lion();
}

但是,这意味着您必须始终将 Animal 声明为正确的动物类型,这样您就失去了拥有该基类的某些好处.

This, however, means you always have to declare Animal as the right type of animal so you lose some of the benefits of having this base class.

这篇关于子类作为返回类型的泛型重写方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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