c# - 具有强类型返回类型的抽象方法

标签 c# generics inheritance overriding abstract-class

考虑以下类:

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

public class Monkey : Animal
{
    public override Animal GiveBirth()
    {
        return new Monkey();
    }
}

public class Snake : Animal
{
    public override Animal GiveBirth()
    {
        return new Snake();
    }
}

//That one doesnt makes sense.
public class WeirdHuman: Animal
{
    public override Animal GiveBirth()
    {
        return new Monkey();
    }
}

我正在寻找一种方法来强制执行覆盖的 GiveBirth 方法的返回类型,以便它始终返回实际的类类型,这样 WeirdHuman 就不会生 child 给猴子

我觉得答案是关于泛型类型的,但我不知道该怎么做。

预期结果示例:

public abstract class Animal
{
    public abstract /*here a way to specify concrete type*/ GiveBirth();
}

public class Monkey : Animal
{
    public override Monkey GiveBirth() //Must returns an actual Monkey
    {
        return new Monkey();
    }
}

如果解释清楚,“绝对不可能”可能是一个答案。

最佳答案

这是协变返回,C# 不支持。我每天都为此哀叹。您希望绕过它的最好方法是使用通用返回类型并在通用类型上指定 where 条件,但这也可能导致您在匹配通用参数要求的过程中遇到其他问题。

public abstract class Animal<TBirthType> where TBirthType : Animal<TBirthType>
{
    public abstract TBirthType GiveBirth();
}

public class Monkey<TBirthType> : Animal<TBirthType> where TBirthType : Monkey<TBirthType>
{
    public override TBirthType GiveBirth()
    {
        return new Monkey<Monkey>();
    }
}

或者,如果您不需要任何进一步的继承,您可以关闭泛型。

public class Monkey : Animal<Monkey>
{
    public override Monkey GiveBirth()
    {
        return new Monkey();
    }
}

请注意,单独的协变性仍然不足以确保不会形成行为不当的派生类型,但它允许将返回的类型指定为正在使用的类型。尽管如此,仍然没有办法从抽象类中锁定它。您或许可以通过在运行时检查类型的基本级别实现的方法的反射来管理运行时检查,但这也可能非常困惑。

关于c# - 具有强类型返回类型的抽象方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16172100/

相关文章:

c# - 类型 xxxx 不应使用 xmlinclude 或 soapinclude

c# - 如果我指定了基类,为什么我不能用泛型调用参数化构造函数

python - 类属性的类型提示

c# - 通用类和 Type.GetType()

c++ - 使用 CRTP 的模板中的继承类型

C# 接口(interface)和类型伪装

c# - 用于制作游戏引擎的C#或C++(深入)

javascript - Knockout.mapping.fromJSON 因 ' 字符而失败

c# - 将 C# 对象转换为 JSON 或 Javascript 对象

java - List<Dog> 是 List<Animal> 的子类吗?为什么 Java 泛型不是隐式多态的?