免责声明
请不要只是投票关闭这个,因为标题看起来很主观,如果之前有人问过,请指出我在评论中的上一个问题,我会删除这个 - 我真的看了高低都试图找到关于这个主题的先前问题。
背景
鉴于我有以下界面和具体实现:
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()。我不确定在后台有多少优化,但是逻辑表明它现在必须通过枚举它们来计算项目,这对性能不利。如果我只是将数组作为数组返回,那么它就是一个直接的属性查找。
答案 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,如果你试图改变他们所依赖的实现细节,你就会打电话给人们。
不好。