我的问题是
接口Set具有方法add(E e),它扩展了接口Collection。接口Collection也有方法add(E e),既然它已经扩展了接口Collection,为什么我们还需要在接口集中使用相同的方法呢?目的是什么?我被困住了
发布于 2010-09-22 17:38:58
既然这两个正确的答案都没能说服你,我就试着解释一下。
接口定义契约-即,它们定义实现者将要(和约束)做什么,这样您就知道,每当您通过接口引用对象时,它都具有严格定义的行为,无论它是如何实现的。
现在,这份合同分为两部分:
下面是具体的Collection / Set示例:
Collection,则您对add的行为一无所知-无论它是否允许重复Set,则您可以确定不允许重复。这种区别是由重新定义的add方法的javadoc实现的。
发布于 2010-09-22 17:15:39
Set.add完善了Collection.add的契约。来自后者的Javadoc:
支持此操作的
集合可能会对可以添加到此集合中的元素进行限制。具体地说,一些集合将拒绝添加null元素,而其他集合将对可能添加的元素类型施加限制。集合类应该在他们的文档中清楚地指定可以添加什么元素的任何限制。
这就是在Set.add的Javadoc中所做的事情,它声明,例如,重复的元素不会添加到集合中。
更新:关于合同和接口
(包括并扩展我在下面的评论,以完善这个答案。)
方法的契约正式或非正式地指定了调用者希望为该方法提供什么输入,以及方法调用的保证结果是什么。例如,约定可能声明不需要任何null参数,如果传递给该方法一个null参数,它将抛出NullPointerException。Collection框架中的Javadoc方法就是这种契约的一个很好的例子。
请注意,一些语言允许甚至要求正式定义契约,因此契约被编译到代码中,并在运行时积极执行。Eiffel就是这样一种语言。然而,Java没有这样的工具;在Javadoc中定义的契约是不正式的,甚至没有为它们定义严格的格式。这些文件仅供人类阅读,JVM没有注意到它们。因此,在Java中,违反约定可能不会立即引起注意,只有在随后产生的bug开始出现时才会注意到。
可以为具体的类方法和抽象/接口方法定义契约。接口的契约是(应该)绑定到它的所有实现的。例如,HashSet.add、TreeSet.add、LinkedHashSet.add等都必须履行Set.add的合同(并可能进一步完善它)。不按照Set.add契约行为的实现破坏了Liskov substitution principle。
发布于 2010-09-22 17:17:27
据我所知,扩展类应该具有与超类指定的方法相同的方法。至于add方法之间的区别,我建议您比较各个add()的javadoc。
https://stackoverflow.com/questions/3767794
复制相似问题