Collection 定义如下
interface Collection<out E>: Iterable<E> {
val size: Int
fun isEmpty(): Boolean
// 剩下的定义
}
List 定义如下
interface List<out E>: Collection<E> {
override val size: Int
override fun isEmpty(): Boolean
// 剩下的定义
}
为何接口和抽象类在实现父接口时,有时候会手动 override 父接口的属性和方法呢?
1
zgbgx1 2017-10-11 11:03:03 +08:00
这就是 继承 和 多态,从 java 来说,List 和 Set 都继承 于 collection 接口,但是 List 和 Set 是不一样的
|
2
zhix OP @zgbgx1 我的意思是,为何要重复声明一遍呢?就好比 Collection 的定义中也重复地 override 声明了 Iterable 的 iterator 方法
|
3
zgbgx1 2017-10-11 11:25:47 +08:00
@zhix List 和 Set 都是继承于 Collection,他们也有各自的区别,所以设计的时候才需要重写,以实现各自的功能,重复声明一遍,当然还有可能为了 层次分明,在 List 和 Set 层规范 size 这个属性和 isEmpty 这个方法,方便 以后的开发。
|
5
vankid 2017-10-11 11:40:22 +08:00
就像上面说的,我猜也是因为软件工程的原因。我理解是:Collection 有其他的继承者,如果只从 List 这一代来看或许你会觉得多余(事实上语法层面确实多余),但是 List 也有不同的继承者,那个时候你再看 List 的时候希望它是空白,而你需要继续往上翻才能看到声明吗?前面这才是三层,如果五层呢,类关系进一步复杂呢?在接口里重复声对当前接口非常重要的方法,这样就比较清晰了。
|
6
zhix OP @vankid @zgbgx1 刚刚看了下 Java 中的声明,Queue 这个接口同样继承自 Collection,但是并没有显式声明 size、isEmpty,但是 List 和 Set 都有。但是 Queue 中声明的 add 和 offer 方法却在子接口 Deque 中被重新声明了。
而且我注意到 Queue 的作者( Doug Lea )与 List/Set 的作者( Josh Bloch,Neal Gafter )不是同一人。所以我猜测重复声明一方面是个人习惯,另一方面是显式告知使用者该方法在当前上下文和父接口上下文中使用方式和含义的差别,比如 Queue 中的 poll 就是 poll,而 Deque 中的 poll 和 pollFirst 等价。 |
7
kaneg 2017-10-11 21:18:42 +08:00 via iPhone 1
我猜还有一个作用,就是如果 List 放弃继承 Collection (我是说假如),那么 List 的子类也不会受影响,因为它还保留了一份方法申明
|