我应该何时返回接口,何时返回具体类?

2022-09-01 14:53:07

在用Java编程时,我几乎总是出于习惯,写这样的东西:

public List<String> foo() {
    return new ArrayList<String>();
}

大多数时候甚至没有想到它。现在的问题是:我应该始终将接口指定为返回类型吗?或者建议使用接口的实际实现,如果是,在什么情况下?

很明显,使用界面有很多优点(这就是为什么它在那里)。在大多数情况下,库函数使用什么具体实现并不重要。但也许在某些情况下它确实很重要。例如,如果我知道我将主要随机访问列表中的数据,那么a将很糟糕。但是如果我的库函数只返回接口,我根本不知道。为了安全起见,我甚至可能需要将列表显式复制到:LinkedListArrayList

List bar = foo();
List myList = bar instanceof LinkedList ? new ArrayList(bar) : bar;

但这似乎很可怕,我的同事可能会在自助餐厅用私刑处死我。这是理所当然的。

你们怎么看?您的准则是什么,您何时倾向于抽象解决方案,以及何时透露实施细节以获得潜在的性能提升?


答案 1

返回相应的接口以隐藏实现详细信息。您的客户应该只关心您的对象提供的内容,而不是您如何实现它。如果您从私有 ArrayList 开始,稍后决定其他内容(例如,LinkedLisk、skip list 等)更合适,那么如果返回接口,则可以在不影响客户端的情况下更改实现。一旦你返回一个具体的类型,机会就失去了。


答案 2

例如,如果我知道我将主要随机访问列表中的数据,那么LinkedList将是坏的。但是如果我的库函数只返回接口,我根本不知道。为了安全起见,我甚至可能需要将列表显式复制到ArrayList。

正如其他人所提到的,你一定不能关心库是如何实现功能的,以减少库的耦合并提高库的可维护性。

作为库客户端,您可以证明实现在您的用例中表现不佳,则可以联系负责人并讨论要遵循的最佳路径(针对这种情况的新方法或只是更改实现)。

也就是说,您的示例具有过早优化的味道。

如果该方法至关重要,它可能会在文档中提及实现详细信息。