一种返回派生类实例的抽象方法

时间:2012-02-20 12:49:56

标签: c# inheritance abstract-class

是否可以创建一个必须返回派生类实例的抽象方法?我可以这样做:

abstract class Base
{
   public abstract Base GetObj();
}

class Derived : Base
{
   public Derived() { }

   public override Base GetObj()
   {
       return new Derived();
   }
}

但我想知道是否有办法让Derived::GetObj()被迫返回Derived

感谢。

2 个答案:

答案 0 :(得分:18)

使用泛型可以实现这一目标:

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

class Derived : Base <Derived>
{
   public Derived() { }

   public override Derived GetObj()
   {
       return new Derived();
   }
}

您甚至可以进一步简化此操作(如果所有派生实例都是使用默认构造函数创建的):

abstract class Base<T>
    where T : Base<T>, new()
{
    public static T GetObj()
    {
        return new T();
    }
}

class Derived : Base<Derived>
{
    public Derived() { }
}

答案 1 :(得分:7)

你拥有的几乎但不完全是一个抽象的工厂。我首先要说的是,您应该将它留给派生类的实现者来使它正确,或者只是相信它们会。

另一个答案显示了所谓的奇怪的重复出现的模板模式。这里有一个基类,它试图使用类型系统来强制派生类型在某些输入中使用自己或输出位置。

public abstract class Foo<T> where T : Foo<T>
public class Bar : Foo<Bar>

这个想法可能适用于其他语言。只有人们正确使用它,它才能在C#中运行。有了Bar的上面定义,现在我也可以有

public class Baz : Foo<Bar> 

这完全合法。 BarFoo<Bar>,这是Baz使用它所需的全部内容。没有什么要求Baz实际使用Foo<Baz>

C#中的类型系统根本无法强制执行您想要强制执行的操作。即使使用此模式,您仍然处于与以前相同的位置。您仍然必须信任派生类的实现者才能正确地完成它。

有关此主题的更多信息,请阅读this blog