集合框架中的接口
我的问题是
接口集有方法add(E e)
,它扩展了接口Collection
。 Interface Collection
也有方法add(E e)
那么为什么我们在接口Set中需要相同的方法,因为它已经扩展了接口Collection
。 什么目的 ? 我坚持这一点
由于这两个正确答案无法说服你,我会试着解释一下。
接口定义了契约 – 即它们定义了要执行的(和绑定的)实现者,因此您知道无论何时通过接口引用对象,它都具有严格定义的行为,无论其实现的具体程度如何 。
现在,这份合同分为两部分:
- 方法签名 – 方法签名是编译器强制执行的元素 – 所有实现者必须符合接口定义的所有方法签名
- 记录的行为 – 当方法比方法签名更多时,记录特殊行为。 它再次告诉客户端接口对所有实现者的期望,尽管它不会在技术上强制实现者遵守它。
这里有具体的Collection
/ Set
示例:
- 如果你将一个对象称为
Collection
,那么你不知道add
任何行为 – 它是否允许重复 - 如果您将对象称为
Set
,则可以确定不允许重复。
这种区别是由重新定义的 add
方法的javadoc完成的。
Set.add
改进了Collection.add
的合约。 来自后者的Javadoc:
支持此操作的集合可能会限制可能添加到此集合的元素。 特别是,某些集合将拒绝添加null元素,而其他集合将对可能添加的元素类型施加限制。 集合类应在其文档中明确指出可以添加哪些元素的任何限制。
这就是在Set.add
的Javadoc中Set.add
,它声明例如重复的元素没有被添加到集合中。
更新:合同和接口
(包括并扩展我的评论以完善这个答案。)
方法的契约指定 – 正式或非正式 – 调用者期望提供的内容作为该方法的输入,以及方法调用的保证结果是什么 。 例如,合同可能声明不期望null
参数,如果方法传递null
参数,它将抛出NullPointerException
。 Collection框架中的方法的Javadoc是此类合同的很好的例子。
请注意,某些语言允许甚至需要合同的正式定义 ,因此合同将编译到代码中并主动强制执行运行时 。 埃菲尔就是这样一种语言。 但是,Java没有这样的设施; Javadoc中定义的合同不是正式的 ,甚至没有为它们定义严格的格式。 这些仅用于人类阅读,而不被JVM忽视。 因此, 用Java破解合同可能不会立即引起注意 ,只有在后来出现错误时才会出现。
可以为具体类方法和抽象/接口方法定义合同。 接口的契约(应该)绑定到它的所有实现。 即HashSet.add
, TreeSet.add
, LinkedHashSet.add
等都必须履行Set.add
的合同(并可能进一步完善它)。 根据Set.add
的约定Set.add
打破了Liskov替换原则 。
据我所知,扩展类应该具有超类指定的相同方法。 至于添加方法之间的差异,我建议你比较相应的add()
s的javadoc
- Set.add(E)
- Collection.add(E)