使用列表还是集合更好?
我有一个在列表中存储一些数据的对象。实现稍后可能会更改,并且我不想将内部实现公开给最终用户。但是,用户必须能够修改和访问此数据集合。目前我有这样的事情:
public List<SomeDataType> getData() {
return this.data;
}
public void setData(List<SomeDataType> data) {
this.data = data;
}
这是否意味着我已经允许内部实现细节泄露?我应该这样做吗?
public Collection<SomeDataType> getData() {
return this.data;
}
public void setData(Collection<SomeDataType> data) {
this.data = new ArrayList<SomeDataType>(data);
}
I have an object that stores some data in a list. The implementation could change later, and I don't want to expose the internal implementation to the end user. However, the user must have the ability to modify and access this collection of data. Currently I have something like this:
public List<SomeDataType> getData() {
return this.data;
}
public void setData(List<SomeDataType> data) {
this.data = data;
}
Does this mean that I have allowed the internal implementation details to leak out? Should I be doing this instead?
public Collection<SomeDataType> getData() {
return this.data;
}
public void setData(Collection<SomeDataType> data) {
this.data = new ArrayList<SomeDataType>(data);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
这取决于,您是否希望您的用户能够对数据建立索引?如果是,请使用列表。两者都是接口,因此您不会泄漏实现细节,实际上,您只需要确定所需的最低功能即可。
It just depends, do you want your users to be able to index into the data? If yes, use List. Both are interfaces, so you're not leaking implementation details, really, you just need to decide the minimum functionality needed.
返回列表符合对最高合适接口的编程。
返回集合会给用户带来歧义,因为返回的集合可以是:Set、List 或 Queue。
Returning a List is in line with programming to the Highest Suitable Interface.
Returning a Collection would cause ambiguity to the user, as a returned collection could be either: Set, List or Queue.
与通过 List.get(int) 对列表进行索引的能力无关,用户(或您)是否期望集合的元素处于可靠且可预测的顺序?该集合可以有多个相同的项目吗?这两个都是对更一般集合中不常见的列表的期望。这些是我在确定向最终用户公开哪个抽象时使用的测试。
Independent of the ability to index into the list via List.get(int), do the users (or you) have an expectation that the elements of the collection are in a reliable and predictable order? Can the collection have multiples of the same item? Both of these are expectations of lists that are not common to more general collections. These are the tests I use when determining which abstraction to expose to the end user.
当返回处于高层次结构中的接口或类的实现时,经验法则是声明的返回类型应该是最高级别,该级别提供您准备向调用者保证的最低功能,并且调用者合理需要。例如,假设您真正返回的是一个 ArrayList。 ArrayList 实现了 List 和 Collection(以及其他)。如果您希望调用者需要使用 get(int x) 函数,那么它无法返回 Collection,您需要返回 List 或 ArrayList。只要您看不出有任何理由要更改实现以使用列表以外的其他内容(例如集合),那么正确的答案就是返回列表。我不确定 ArrayList 中是否有任何不在 List 中的函数,但如果有,同样的推理也适用。另一方面,一旦您返回一个列表而不是集合,您现在就在某种程度上锁定了您的实现。您在 API 中投入的内容越少,对未来改进的限制就越少。
(实际上,在这种情况下我几乎总是返回一个 List,而且它从来没有让我烦恼。但我可能真的应该返回一个 Collection。)
When returning an implementation of an interface or class that is in a tall hierarchy, the rule of thumb is that the declared return type should be the HIGHEST level that provides the minimum functionality that you are prepared to guarantee to the caller, and that the caller reasonably needs. For example, suppose what you really return is an ArrayList. ArrayList implements List and Collection (among other things). If you expect the caller to need to use the get(int x) function, then it won't work to return a Collection, you'll need to return a List or ArrayList. As long as you don't see any reason why you would ever change your implementation to use something other than a list -- say a Set -- then the right answer is to return a List. I'm not sure if there's any function in ArrayList that isn't in List, but if there is, the same reasoning would apply. On the other hand, once you do return a List instead of a Collection, you have now locked in your implementation to some extent. The less you put in your API, the less restriction you put on future improvements.
(In practice, I almost always return a List in such situations, and it has never burned me. But I probably really should return a Collection.)
使用最通用的类型(即 Collection)是最有意义的,除非有某些明确的原因需要使用更具体的类型(List)。但无论你做什么,如果这是一个供公众使用的 API,请在文档中明确它的用途;如果它返回集合的浅表副本,请这么说。
Using the most general type, which is Collection, makes the most sense unless there is some explicit reason to use the more specific type - List. But whatever you do, if this is an API for public consumption be clear in the documentation what it does; if it returns a shallow copy of the collection say so.
是的,如果该方法始终返回列表不是接口契约的一部分,那么您的第一个替代方案确实会泄漏实现细节。此外,允许用户代码替换您的集合实例有些危险,因为它们传入的实现可能不会按照您的预期运行。
当然,这完全取决于您对用户的信任程度。如果您接受 Python 哲学“我们都是同意的成年人”,那么第一种方法就可以了。如果您认为您的库将由缺乏经验的开发人员使用,并且您需要尽一切努力“照顾”他们并确保他们不会做错事,那么最好不要让他们设置集合,甚至不要返回实际的集合。相反,返回它的(浅)副本。
Yes, your first alternative does leak implementation details if it's not part of your interface contract that the method will always return a List. Also, allowing user code to replace your collection instance is somewhat dangerous, because the implementation they pass in may not behave as you expect.
Of course, it's all a matter of how much you trust your users. If you take the Python philosophy that "we're all consenting adults here" then the first method is just fine. If you think that your library will be used by inexperienced developers and you need to do all you can to "babysit" them and make sure they don't do something wrong then it's preferable not to let them set the collection and not to even return the actual collection. Instead return a (shallow) copy of it.
这取决于你想为用户提供什么保证。如果数据是连续的,因此元素的顺序很重要并且您允许重复,则使用列表。如果元素的顺序并不重要,并且可能允许也可能不允许重复,则使用集合。由于您实际上返回的是底层集合,因此您不应该同时拥有 get 和 set 函数,而只能拥有 get 函数,因为返回的集合可能会发生变化。此外,提供 set 函数允许用户更改集合的类型,而您可能希望由您控制特定类型。
It depends on what guarantees you want to provide the user. If the data is sequential such that the order of the elements matter and you are allowing duplicates, then use a list. If order of elements does not matter and duplicates may or may not be allowed, then use a collection. Since you are actually returning the underlying collection you should not have both a get and set function, only a get function, since the returned collection may be mutated. Also, providing a set function allows the type of collection to be changed by the user, whereas you probably want for the particular type to be controlled by you.
如果我担心向外部用户隐藏数据的内部表示,我会使用 XML 或 JSON。不管怎样,它们都是相当普遍的。
Were I concerned with obscuring internal representation of my data to an outside user, I would use either XML or JSON. Either way, they're fairly universal.