从方法返回子类或接口实现的最佳实践是什么?

时间:2010-09-23 02:03:12

标签: language-agnostic

免责声明

请不要只是投票关闭这个,因为标题看起来很主观,如果之前有人问过,请指出我在评论中的上一个问题,我会删除这个 - 我真的看了高低都试图找到关于这个主题的先前问题。

背景

鉴于我有以下界面和具体实现:

public interface IFoo 
{
   // Some stuff
}
public class Foo : IFoo
{
   // Concrete implementations of stuff
}

在某处我有以下方法:

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

我传统上总是返回Foo,看到,因为它本身就是IFoo ,所以它可以作为IFoo在另一端消费:

IFoo foo = GiveMeAFoo();

我可以看到的主要优点是,如果我真的需要在某处使用Foo作为具体实现,我可以。

实际问题

我最近在另一个问题上遇到了一些评论,让某人很难做到这一点,建议返回类型应为IFoo

我错了还是他们?任何人都可以告诉我为什么返回具体实现是一个坏主意?

我知道在接收方法的参数时需要IFoo是有意义的,因为参数越不具体,方法越有用,但肯定会使返回类型特定是无理限制的

修改

使用IFoo和Foo可能太模糊了。这是.NET的一个具体示例(在.NET中,数组实现IEnumerable - 即string[] : IEnumerable<string>

public string[] GetMeSomeStrings()
{
    return new string[] { "first", "second", "third" };
}

肯定在这里返回IEnumerable是一个坏主意?要获取length属性,您现在必须调用Enumerable.Count()。我不确定在后台有多少优化,但是逻辑表明它现在必须通过枚举它们来计算项目,这对性能不利。如果我只是将数组作为数组返回,那么它就是一个直接的属性查找。

4 个答案:

答案 0 :(得分:3)

如果您希望自己的方法最灵活,则应返回最少派生类型(在您的情况下为IFoo):

public interface IFoo { }

public class Foo : IFoo { }

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

这将允许您更改方法的IFoo内部的具体实现,而不会破坏任何消耗您的方法的人:

public interface IFoo { }

public class Foo : IFoo { }

public class Foo2 : IFoo { }

public IFoo GiveMeAFoo() { return new Foo2(); }

答案 1 :(得分:1)

您可以创建一堆接口并将其提供给不同的团队。举个例子

public interface IFoo 
{
   // Some stuff
}

public interface IBar
{
    public IFoo getMeAFoo();
}

然后,您可以将这些界面提供给开发前端应用程序的人员,而且他不必知道具体实现是什么。开发前端的人可以使用getMeAFoo()方法知道它返回IFoo的对象,而具体的实现可以单独开发:

public class Foo implements IFoo
{
    // more stuff
}

public class MoreFoo implements IFoo
{
    //
}

public class WunderBar implements IBar
{
    public IFoo getMeAFoo()
    {
        case 1:
            return new Foo();
        case 2:
            return new MoreFoo();
    }
}

希望这是有道理的:)

答案 2 :(得分:1)

在我看来,返回最抽象的类型总是更好。如果你发现自己需要任何特定于你实际返回类型的东西,我会认为这是代码味道。

这样做的主要优点是您可以改变主意,了解您真正希望返回的类型。被调用的方法与其调用者进行了更强烈的解耦

此外,您可以删除依赖项。调用者代码不需要知道您选择创建的实际类型。

我的最后一句话是Eric Lippert的引文:“You probably should not return an array as the value of a public method or property”。 (他的文章主要关注C#,但总体思路与语言无关)

答案 3 :(得分:0)

很好,无论你在哪里使用它,你都使用IFoo foo = GiveMeAFoo();

然后其他人使用你的代码并且不会那样使用它,无论出于什么原因,他们使用Foo foo = GiveMeAFoo();

现在他们看到Foo的所有功能都不是(有充分理由)IFoo的一部分。现在,他们可以使用不属于界面的部分实现。现在你不能在不破坏代码的情况下改变你的实现,你的实现现在是公共API,如果你试图改变他们所依赖的实现细节,你就会打电话给人们。

不好。