Kotlin的继承
1、超类:Any
类似于Java中的Object类,Kotlin也有一个叫Any的超类,是所有类的父类,所有类都默认继承自该类。超类的定义如下,其中定义了三个函数:
package kotlin
/**
* The root of the Kotlin class hierarchy. Every Kotlin class has [Any] as a superclass.
*/
public open class Any {
public open operator fun equals(other: Any?): Boolean
public open fun hashCode(): Int
public open fun toString(): String
}
2、open
注意上面的Any类用open修饰,表示该类可以被继承。Kotlin中的类默认都是final的,无法被继承:

如果想让类可以被继承,就需要用在定义类的地方用open关键字标识该类可以被继承。
//父类open,可以被继承
open class Base {
//
}
//继承上面的类
class Sub : Base() {
//
}
3、构造器
继承中涉及到的子类和父类构造器调用。关于类的构造器参考《类和对象》。
3.1、父类无主构造器
3.1.1、无次构造器
子类只需调用父类的无参构造器即可。
①在子类的主构造器处调用
open class Base {
}
//调用父类的默认无参构造器
class Sub : Base() {
}
②在子类的次级构造器中调用:
open class Base {
}
class Sub : Base {
constructor() : super() {
//子类次级构造器
}
}
3.1.2、有次级构造器
①无参次级构造器
//父类有次级构造器
open class Base {
constructor() {
}
}
//在子类的次级构造器调用父类的次级构造器
class Sub : Base {
constructor() : super() {
}
}
//在子类的主级构造器调用父类的次级构造器
class Sub : Base() {
}
②有参次级构造器
open class Base {
var num: Int
constructor(num: Int) {
this.num = num
}
}
//在子类主构造器中调用父类有参次级构造器
class Sub(num:Int) : Base(num) {
}
//子类次级构造器调用父类有参次级构造器
class Sub : Base {
constructor(num: Int) : super(num) {
}
}
3.2、父类有主构造器
3.2.1、父类无参主构造器
相当于与 3.1.1
open class Base() {
}
//调用父类无参主构造器
class Sub : Base() {
}
3.2.2、父类有参主构造器
①子类主构造器中调用父类主构造器
open class Base(var num: Int) {
}
class Sub(num: Int) : Base(num) {
}
②子类次级构造器中调用父类主构造器
open class Base(var num: Int) {
}
class Sub : Base {
constructor(num: Int) : super(num) {
}
}
注意:
下面这样的写法编辑器没有报错

但是运行是会报错:
Kotlin: Explicit 'this' or 'super' call is required. There is no constructor in superclass that can be called without arguments
4、重写
使用fun定义函数的时候,函数默认都是final的,不能被继承重写。

4.1、重写父类方法
想要子类能够继承重写该方法,用open关键字修饰这个函数。
open class Base {
open fun make() {
//子类能够重写需要加open修饰
}
}
class Sub : Base() {
override fun make() {
//必须加上override修饰,表示重写父类方法
}
}
4.2、调用父类方法
①通过super调用父类的方法
open class Base {
open fun make() {
println("Base")
}
}
class Sub : Base(){
override fun make() {
super.make() //调用父类Base的make()方法
}
}
②如果从父类通过继承获得了两个相同前面的函数,需要指定。
定义一个类和一个接口,它们都有一个签名一样的方法make()
open class Base {
open fun make() {
println("Base")
}
}
open interface OtherBase {
open fun make() {
println("OtherBase")
}
}
直接用super调用是不行的。

需要明确指定调用哪一个父类的方法,使用super<父类>.fun,调用指定哪一个父类的方法。
class Sub : Base(), OtherBase {
override fun make() {
super<Base>.make()
}
}
5、属性重写
使用open修饰符标识属性可以被子类重写
open class Base {
open val num: Int = -1
get() = field
}
在子类中使用override
class Sub : Base() {
override var num: Int = 1
}
val修饰的父类属性可以被子类修改为var修饰。
var修饰的父类属性,不能被子类修改为val:

java继承Kotlin父类,只能通过getter/setter访问Kotlin父类中的成员变量。
而Kotlin继承自Kotlin父类,那么可以直接访问Kotlin父类中的非私有成员变量。
6、抽象类
使用关键字abstract修饰抽象类和抽象成员。不需要再用open修饰。
abstract class Animal {
abstract fun getType()
}
类可以继承声明为抽象的类,并实现其中的方法。
class Dog : Animal() {
override fun getType() {
}
}
参考资料:
Kotlin 继承
Kotlin中级篇(四):继承类详解
Kotlin最简单的入门教程——类和继承