返回自己类型的方法的接口

时间:2010-06-15 13:39:44

标签: c# inheritance interface

我有一个班级

的情况
class Foo
{
    Foo Bar()
    {
        return new Foo();
    }
}

现在我想为它创建一个界面

class IFoo
{
    ??? Bar();
}

什么应该代替问号?每个类都应该返回它自己的类型,而不是Foo。

以下解决方案有效,但看起来并不干净。我不明白为什么我必须两次指定同一个类,并且当前类型没有类似“this”

这就是我以后使用它的方式

class GenericClass<T> where T : IFoo
{ 
    T foo = new T();
    T item = foo.Bar();
}

7 个答案:

答案 0 :(得分:11)

你问:

  

以下解决方案有效,但看起来并不干净。我不明白为什么我必须两次指定同一个类,并且当前类型没有类似“this”

您必须指定两次的原因是因为C#缺少您需要的功能。 你想要的是这样的:

interface IFoo
{
    IFoo Bar();
}

class Foo : IFoo
{
    Foo Bar() // should work since Foo is an IFoo, but it's not supported by C#
    {
        return new Foo();
    }
}

从类型安全的角度来看,这应该有效(它被称为return type covariance)。事实上,其他编程语言(如C ++或Java)支持此功能,请参阅this example on Wikipedia。不幸的是,C#不支持返回类型协方差(甚至不是C#4.0,它引入了泛型的协方差),这就是为什么你必须使用其他答案中说明的“泛型解决方法”。

协变返回类型以及“this”类型是新版C#的建议功能:

答案 1 :(得分:8)

您可以使用接口类型添加泛型类型并对其进行约束:

public interface IFoo<T>
{
    T Bar();
}

您可以按如下方式实现:

public class Foo : IFoo<Foo>
{
    public Foo Bar()
    {
        return new Foo();
    }
}

public class Cheese : IFoo<Cheese>
{
    public Cheese Bar()
    {
        return new Cheese();
    }
}

更新,如果您从不关心Foo的具体返回类型,那么您可以执行以下操作:

public interface IFoo
{
    IFoo Bar();
}

实现方式如下:

public class Foo : IFoo
{
    public IFoo Bar()
    {
        return new Foo();
    }
}

然后在你的通用类中:

public class GenericClass<T> where T : class, IFoo, new()
{
    public T Rar()
    {
        T foo = new T();
        T item = foo.Bar() as T;
        return item;
    }
}

GenericClass<Foo>.Rar();将是Foo的具体实现。

答案 2 :(得分:4)

我认为真正的问题是:为什么你需要界面中的派生类型?接口正是出于这个原因 - 从具体类中抽象出来。如果只是为了方便,那么在调用Bar()之后你不必强制转换为Foo,你可以明确地实现接口:

interface IFoo
{
    IFoo Bar();
}

class Foo : IFoo
{
    public Foo Bar()
    {
        return new Foo();
    }

    IFoo IFoo.Bar()
    {
        return Bar();
    }
}

问自己一个问题:为什么在需要具体类型时引入界面?

答案 3 :(得分:2)

您可以使用抽象基类和显式成员实现来实现此目的。首先,声明你的界面:

interface IFoo
{
    IFoo Bar();
}

然后,声明一个以显式方式实现IFoo的通用抽象类,并声明一种抽象方法,即“重载”Bar(),但是以通用方式:

abstract class BaseFooImpl<T> : IFoo where T : BaseFooImpl
{
    public abstract T Bar();

    IFoo IFoo.Bar()
    {
        return Bar(); // this will call the abstract Bar()
    }
 }

现在,定义你的具体类:

class ConcreteFoo : BaseFooImpl<ConcreteFoo>
{
   public override ConcreteFoo Bar()
   {
      return this; // for example, of course.
   }
}

这种方法的优点是您始终可以使用非通用IFoo引用来保存具体实例。如果你使你的界面通用,你不能,例如,声明这些:

IFoo mammalInstance, fishInstance; // Instead of IFoo<Mammal> mammalInstance; IFoo<Fish> fishInstance;
List<IFoo> manyInstances; // Instead of List<IFoo<IFoo>>, which doesn't even work AFAIK

答案 4 :(得分:0)

public interface IFoo<T>
{
    T Bar();
}

您的实施将是:

class Foo : IFoo<Foo>
{
    Foo Bar()
    {
        return new Foo();
    }
}

class Baz : IFoo<Baz>
{
    Baz Bar()
    { 
        return new Baz(); 
    }
}

答案 5 :(得分:0)

您需要使接口通用,如下所示:

interface IFoo<TClass> where TClass : IFoo<TClass>, class {
    TClass Bar();
}

答案 6 :(得分:0)

不确定你想要完成什么,但可以这样做:

interface IFoo<T>
{
    T Bar();
}



   class Foo:IFoo<Foo>
    {

        #region IFoo<Foo> Members

        public Foo Bar()
        {
            return new Foo();
        }

        #endregion
    }

或者像这样:

    interface IFoo
    {
        IFoo Bar();
    }

class Foo : IFoo
    {

        #region IFoo Members

        public IFoo Bar()
        {
            return new Foo();
        }

        #endregion
    }