Java集合:接口和抽象类

3

请先阅读 http://docs.oracle.com/javase/tutorial/collections/index.html。 - artbristol
1
答案的一部分已经在javadoc中了。接口是没有实现的契约,而抽象类是带有一些实现的契约。这将取决于您的需求,您可能希望依赖现有的实现(抽象),或者您可能会发现后者不适合您的项目(接口)。 - VirtualTroll
对我来说,这些接口似乎除了集合之外没有其他用途,而这些抽象骨架类就是所需的一切。 - jellyfication
4个回答

7
接口存在的原因是为了能够将类型分配给变量或参数,而不强加实现。
例如,如果我创建一个用于在Hibernate中使用的持久实体,并且它有一些东西的集合,我想将List或Set类型分配给它。Hibernate将使用一些特定于Hibernate的实现替换任何我初始化的列表,该实现具有延迟加载或其他所需的功能。Hibernate开发人员可能不想受到必须扩展抽象类的限制。
抽象类是为实现者提供方便而存在的。接口是客户端使用的契约。

这个。这是非常明智的建议。 - Shark
1
@Jellyfication:是的,接口不会强制实施任何特定的实现。大多数情况下,如果你有一个Map、Set或List,你希望能够编写不关心实现的代码(我并不是说实现不重要,只是你想分离关注点)。 - Nathan Hughes
好的,我现在可能明白了。我大概想到了AbstractList非常轻量级(有很少的实现或者没有人会受到这种实现的限制),以至于它可以替代接口本身。或者类似这样的解释。 - jellyfication
1
@Jellification:抽象类中仍有一些实现。当你需要设计一个API时,你会遇到的问题之一是你无法预见人们将要做什么,而且你不想毫无必要地限制他们(特别是因为你未来的自己很可能也是那些不可预测的人之一)。因此,接口的作用是提供一个最小的契约,规定了期望的行为,但没有对实现施加任何限制。由于他们的决策很难或根本无法撤回,这使得API编写者非常谨慎。 - Nathan Hughes
2
@Jellification:接口是API设计者为了为客户端提供有用的东西而想要承诺的绝对最低限度。抽象类提供实现者可能会发现有用的公共功能,但不强制使用。 - Nathan Hughes
显示剩余4条评论

2
实现接口与继承抽象类有很大不同。
假设Animal类是一个抽象类,而Dog、Cat、Snake和Shark都是它的子类。
默认的Animal.move()实现只是移动它们。
但是,接口允许我们进一步分组相似的动物,例如RunningAnimal、SwimmingAnimal。
因此,如果Dog继承Animal并实现了RunningAnimal,除了继承的move()之外,他还必须实现自己的run(),这可能会在从Animal继承的重写move()中找到它的位置。这对你有意义吗?或者我需要更好地解释一下/用一些代码来说明呢? :)
接口可以让你将不同类的相似功能分组起来。“Clickable”、“Sortable”、“Serializable”……它们都通过共享功能(因此可点击列表不仅仅是按钮列表)而包含成员,而不是相同的目的。
所以,就像这样考虑它:
Cat extends Animal implements RunningAnimal, ClimbingAnimal  -- inherits move() has to implement run() and climbTree()
Dog extends Animal implements RunningAnimal  -- inherits move(), has to implement run()
Snake extends Animal                         -- likely overrides inherited move()
Shark extends Animal implements SwimmingAnimal -- likely overrides move(), has to implement swim()

对我来说,这些接口似乎除了集合之外没有其他用途,而这些抽象骨架类就是所需的一切。 - jellyfication
1
有时候接口也被用来在实际实现之前解决问题。当你在团队中工作时,周一达成接口协议是很有用的,这样到了周五,你就不会遇到任何集成代码的问题,因为你从一开始就知道它应该如何交互 :) - Shark

1
为什么不呢?抽象类的作用在于简化继承过程。当您想要创建自己的集合时,您不必从头开始做所有事情。
但是当然没有人告诉您应该从AbstractCollection继承。您可以从头开始编写自己的实现。
对于API来说,拥有接口并区分实现和接口是一种常见的良好做法。

1

接口是用户和实现者之间达成的一种契约。抽象基类旨在作为一个通用基础类来访问一些行为类似的对象。


抽象类可以被使用,但是使用接口更加方便,因为它不承载任何实现。有点像一种约定。就是这样吗? - jellyfication
这不是一个惯例,而是一个具体问题。有时候你需要一个接口,有时候你需要一个常用的共享实现,你希望进一步完善它。 - Shark

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接