为什么 List 继承 Collection 接口时要重新 override 父接口的属性和方法

2017-10-11 10:44:22 +08:00
 zhix

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 父接口的属性和方法呢?

6631 次点击
所在节点    Kotlin
9 条回复
zgbgx1
2017-10-11 11:03:03 +08:00
这就是 继承 和 多态,从 java 来说,List 和 Set 都继承 于 collection 接口,但是 List 和 Set 是不一样的
zhix
2017-10-11 11:14:19 +08:00
@zgbgx1 我的意思是,为何要重复声明一遍呢?就好比 Collection 的定义中也重复地 override 声明了 Iterable 的 iterator 方法
zgbgx1
2017-10-11 11:25:47 +08:00
@zhix List 和 Set 都是继承于 Collection,他们也有各自的区别,所以设计的时候才需要重写,以实现各自的功能,重复声明一遍,当然还有可能为了 层次分明,在 List 和 Set 层规范 size 这个属性和 isEmpty 这个方法,方便 以后的开发。
zgbgx1
2017-10-11 11:28:29 +08:00
@zhix 更多是 软件开发和设计模式的考虑
vankid
2017-10-11 11:40:22 +08:00
就像上面说的,我猜也是因为软件工程的原因。我理解是:Collection 有其他的继承者,如果只从 List 这一代来看或许你会觉得多余(事实上语法层面确实多余),但是 List 也有不同的继承者,那个时候你再看 List 的时候希望它是空白,而你需要继续往上翻才能看到声明吗?前面这才是三层,如果五层呢,类关系进一步复杂呢?在接口里重复声对当前接口非常重要的方法,这样就比较清晰了。
zhix
2017-10-11 12:20:25 +08:00
@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 等价。
kaneg
2017-10-11 21:18:42 +08:00
我猜还有一个作用,就是如果 List 放弃继承 Collection (我是说假如),那么 List 的子类也不会受影响,因为它还保留了一份方法申明
zhix
2017-10-12 10:09:28 +08:00
@kaneg 有道理
aiyaa
2018-11-26 21:44:12 +08:00
@kaneg 有道理

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/396685

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX