7.6 继承
继承是面向对象编程的一个重要的方式,因为通过继承,子类就可以扩展父类的功能。
在Kotlin中,所有的类会默认继承Any这个父类,但Any并不完全等同于java中的Object类,因为它只有equals(),hashCode()和toString()这三个方法。
7.6.1 open类
除了抽象类、接口默认可以被继承(实现)外,我们也可以把一个类声明为open的,这样我们就可以继承这个open类。
当我们想定义一个父类时,需要使用open关键字:
open class Base{
}
当然,抽象类是默认open的。
然后在子类中使用冒号:
进行继承
class SubClass : Base(){
}
如果父类有构造函数,那么必须在子类的主构造函数中进行继承,没有的话则可以选择主构造函数或二级构造函数
//父类
open class Base(type:String){
}
//子类
class SubClass(type:String) : Base(type){
}
Kotlin中的override
重写和java中也有所不同,因为Kotlin提倡所有的操作都是明确的,因此需要将希望被重写的函数设为open:
open fun doSomething() {}
然后通过override标记实现重写
override fun doSomething() {
super.doSomething()
}
同样的,抽象函数以及接口中定义的函数默认都是open的。
override重写的函数也是open的,如果希望它不被重写,可以在前面增加final :
open class SubClass : Base{
constructor(type:String) : super(type){
}
final override fun doSomething() {
super.doSomething()
}
}
7.6.2 多重继承
有些编程语言支持一个类拥有多个父类,例如C++。 我们将这个特性称之为多重继承(multiple inheritance)。多重继承会有二义性和钻石型继承树(DOD:Diamond Of Death)的复杂性问题。Kotlin跟Java一样,没有采用多继承,任何一个子类仅允许一个父类存在,而在多继承的问题场景下,使用实现多个interface 组合的方式来实现多继承的功能。
代码示例:
package com.easy.kotlin
abstract class Animal {
fun doEat() {
println("Animal Eating")
}
}
abstract class Plant {
fun doEat() {
println("Plant Eating")
}
}
interface Runnable {
fun doRun()
}
interface Flyable {
fun doFly()
}
class Dog : Animal(), Runnable {
override fun doRun() {
println("Dog Running")
}
}
class Eagle : Animal(), Flyable {
override fun doFly() {
println("Eagle Flying")
}
}
// 始祖鸟, 能飞也能跑
class Archaeopteryx : Animal(), Runnable, Flyable {
override fun doRun() {
println("Archaeopteryx Running")
}
override fun doFly() {
println("Archaeopteryx Flying")
}
}
fun main(args: Array<String>) {
val d = Dog()
d.doEat()
d.doRun()
val e = Eagle()
e.doEat()
e.doFly()
val a = Archaeopteryx()
a.doEat()
a.doFly()
a.doRun()
}
上述代码类之间的关系,我们用图示如下:
我们可以看出,Archaeopteryx继承了Animal类,用了父类doEat()函数功能;实现了Runnable接口,拥有了doRun()函数规范;实现了Flyable接口,拥有了doFly()函数规范。
在这里,我们通过实现多个接口,组合完成了的多个功能,而不是设计多个层次的复杂的继承关系。