2

我有一个基类,它的方法可以被覆盖。如果我从这个基类继承一个类,我怎样才能让方法返回继承的类型?

喜欢:

public class ClassA : BaseClass
{
    public override ClassA TestMethod(...)
    {
        // ...
    }   
}

我需要手动向基类提供类型吗?或者我可以让它自动提供那种类型吗?

4

3 回答 3

8

您可以使用泛型类型来执行此操作。

public class BaseClass<T> where T : BaseClass<T> {
    public abstract T TestMethod(...);
}

public class ClassA : BaseClass<ClassA>
{
    public override ClassA TestMethod(...)
    {
        // ...
    }   
}

你为什么需要它?可能会导致更合适的答案...

于 2013-01-08T15:26:18.453 回答
7

您想要的功能有一个名称;这是返回类型协方差

C# 不支持它的原因如下:

为什么 C# 在实现接口时不允许继承返回类型

其他答案都建议您使用 C# 版本的奇怪重复模板模式来解决您的问题。我的观点是,这种模式带来的问题多于解决的问题。有关详细信息,请参阅我关于该主题的文章:

http://blogs.msdn.com/b/ericlippert/archive/2011/02/03/curiouser-and-curiouser.aspx

解决此问题的更好方法是使用此模式:

abstract class Animal
{
    protected abstract Animal ProtectedGetMother();

    public Animal GetMother()
    {
      return this.ProtectedGetMother();
    }
}
class Cat : Animal
{
    protected override Animal ProtectedGetMother()
    {
      do the work particular to cats here
      make sure you return a Cat
    }
    public new Cat GetMother()
    {
      return (Cat)this.ProtectedGetMother();
    }
 }

问题是您不能覆盖具有不同返回类型的虚拟方法。所以不要。创建一个具有不同返回类型的全新方法,并使虚拟方法成为类层次结构的实现细节

Cat : Animal<Cat>这种技术比这种“猫是猫的动物”的胡说八道要容易理解大约十亿倍。

于 2013-01-08T16:10:09.170 回答
2

您可以以通用方式执行此操作:

public abstract class Base
{
    public abstract T AbstractTestMethod<T>() where T : Base;

    public virtual T VirtualTestMethod<T>() where T : Base, new()
    {
        return new T();
    }
}

public class ClassA : Base
{
    public override ClassA AbstractTestMethod<ClassA>()
    {
        return new ClassA();
    }

    public override ClassA VirtualTestMethod<ClassA>()
    {
        return new ClassA();
    }
}

使用虚拟方法的行为不像使用抽象方法那么严格。使用抽象方式,您可以强制开发人员自行实现该方法。使用虚拟方式,您可以告诉他们诸如“满足我的约束并随意使用默认行为”之类的内容。

于 2013-01-08T15:29:52.233 回答