为什么 Collections 类包含独立(静态)方法,而不是将它们添加到 List 接口中?
对于 Collections 中的所有方法List 作为他们的第一个参数,为什么这些方法不就是 List 接口的一部分吗?
我的直觉是:给定一个 List 对象,该对象本身应该“知道”如何对其自身执行操作,例如rotate()、shuffle() 或reverse()。但相反,作为一名 Java 程序员,我必须检查 List 接口中的方法以及 Collections 类中“那边”的静态方法,以确保我使用规范的解决方案。
为什么某些方法作为静态独立方法放置在 Collections 类中,而不是添加到 List 接口中(并且可能因此由某些现有或可能的基类实现)?
我试图更好地理解 Java 集合框架背后的设计决策。
这里是否有一些我忽略的引人注目的 OO 设计原则?或者这种区别只是出于某些实际的性能原因?
For all the methods in Collections that take a List as their first argument, why aren't those methods simply part of the List interface?
My intuition is: given a List object, that object itself should "know" how to perform on itself operations such as rotate(), shuffle(), or reverse(). But instead, as a Java programmer, I have to review both the methods in the List interface, as well as the static methods "over there" in the Collections class, to ensure I'm using a canonical solution.
Why were some methods placed as static standalone methods in the Collections class, instead of being added to the List interface (and presumably thus implemented by some existing or would-be base class)?
I'm trying to better understand the design decisions behind the Java collections framework.
Is there some compelling OO design principle here that I'm overlooking? Or was this distinction done simply for some practical, performance reason?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
关键是,给定合适的原始操作(删除、设置等),可以实现一次更高级的操作(排序、随机播放、二分搜索),而不是由每个列表实现来实现。
实际上,java.util.Collections 就像 .NET 的 Enumerable 类 - 充满了可以在任何集合上工作的通用方法,以便它们可以共享单个实现并避免重复。
The point is that given suitable primitive operations (remove, set etc) a bunch of more high level operations (sort, shuffle, binary search) can be implemented once rather than being implemented by every single list implementation.
Effectively, java.util.Collections is like .NET's Enumerable class - full of general purpose methods which can work on any collection, so that they can share a single implementation and avoid duplication.
List 接口方法背后的理性
Java 的作者们现在可能会以非常不同的方式做事,因为他们对 API 的多年使用有了后见之明和看法。也就是说,C# IList 接口与 Java 非常相似,并且 C# 的作者确实有这样的观点。
Rational Behind the List Interface's Methods
The authors of Java may do things very differently now that they have hindsight and perspective of many years of usage of the API. That said the C# IList interface is quite similar to Java's and C#'s authors did have the perspective.
这在某种程度上肯定是一个判断。我认为要考虑的主要权衡是:当您向接口添加方法时,该接口的每个实现者都必须编写代码来实现它。
如果该方法的语义使得接口的不同实现最好以非常不同的方式实现这些语义,那么最好将其放入接口中。 (当然,如果语义根本无法根据接口中的其他方法来定义,那么它必须是接口中它自己的方法。)
另一方面,如果语义是这样它们就可以根据接口中的其他方法来定义,并且接口的实现者只会一遍又一遍地编写相同的代码,那么最好创建一个实用方法,将接口的实例作为争论。
It's certainly a judgement call at some level. I think the main trade-off to consider is this: When you add a method to an interface, every implementer of that interface must write code to implement it.
If the semantics of that method are such that different implementations of the interface will best implement those semantics in very different ways, then it's better to put it in the interface. (Of course, if the semantics simply can't be defined in terms of other methods in the interface, then it must be its own method in the interface.)
On the other hand, if the semantics are such that they can be defined in terms of other methods in the interface, and implementers of the interface will just tend to write the same code over and over again, then it's better to make a utility method that takes an instance of the interface as an argument.
它们是实用方法,而不是核心列表功能。如果您添加了可以在列表上执行的所有可能的操作,则列表界面只会变得臃肿。 Collections 中的操作不需要了解 List 的内部结构,它们在公共接口上进行操作,因此可以愉快地生活在外部类中。
They are utility methods and not core List functionality. The List interface would just get bloated if you added every possible operation you could do on a List. And the operations in Collections do not need to know about the internals of a List, they operate on the public interface so can happily live in an external class.
这里有两个解释:
历史:Collections类是在List接口之后创建的。设计人员选择保留现有接口的向后兼容性。否则很多开发人员将不得不更改他们的代码。
逻辑:您正在讨论的方法不需要有关列表实现的内部知识,并且可以在实现它的任何集合上实现。
There are two explanations here:
Historical: Collections class was created after List interface. Designers chose to preserve backward compatibility of already existing interface. Otherwise a lot of developers would have to change their code.
Logical: The methods you are talking about do not require internal knowledge on List implementation and can be implemented over ANY collection implementing it.