Kotlin 极简教程(10)- 继承

继承

在 Kotlin 中所有类都有一个共同的超类 Any ,对于没有超类声明的类是默认超类
要声明一个显式的超类,需要把父类名放到类头的冒号之后

open class Base()

class SubClass() : Base()

当中,类上的 open 标注与 Java 中的 final 含义相反,用于允许其它类从这个类继承。默认情况下,Kotlin 中所有的类都是 final

覆盖方法

与 Java 不同,Kotlin 需要显式标注可覆盖的成员和覆盖后的成员:

open class Base() {
    open fun fun1() {

    }

    fun fun2() {

    }
}

class SubClass() : Base() {
    override fun fun1() {
        super.fun1()
    }
}

用 open 标注的函数才可以被子类重载,子类用 override 表示该函数是要对父类的同签名函数进行覆盖
标记为 override 的成员本身也是开放的,也就是说,它可以被子类覆盖。如果想禁止再次覆盖,可以使用 final 关键字标记
如果父类没有使用 open 对函数进行标注,则子类不允许定义相同签名的函数
对于一个 final 类(没有用 open 标注的类)来说,使用 open 标记属性和方法是无意义的

属性覆盖

属性覆盖与方法覆盖类似。在超类中声明为 open 的属性,如果要进行覆盖则必须在派生类中重新声明且以 override 开头,并且它们必须具有兼容的类型
每个声明的属性可以由具有初始化器的属性或者具有 getter 方法的属性覆盖

open class Base() {
    open val x = 10

    open val y: Int
        get() {
            return 100
        }
}

class SubClass() : Base() {
    override val x = 100

    override var y = 200
}

fun main(args: Array<String>) {
    val base = Base()
    println(base.x) //10
    println(base.y) //100
    val subClass = SubClass()
    println(subClass.x) //100
    println(subClass.y) //200
}

此外,也可以用一个 var 属性覆盖一个 val 属性,但反之则不行
因为一个 val 属性本质上声明了一个 getter 方法,而将其覆盖为 var 只是在子类中额外声明一个 setter 方法

在 Kotlin 中,如果一个类从它的直接超类和实现的接口中继承了相同成员的多个实现, 则必须覆盖这个成员并提供其自己的实现来消除歧义
为了表示采用从哪个超类型继承的实现,使用由尖括号中超类型名限定的 super 来指定,如 super

open class BaseClass {
    open fun fun1() {
        println("BaseClass fun1")
    }
}

interface BaseInterface {
    //接口成员默认就是 open 的
    fun fun1() {
        println("BaseInterface fun1")
    }
}

class SubClass() : BaseClass(), BaseInterface {
    override fun fun1() {
        //调用 SubClass 的 fun1() 函数
        super<BaseClass>.fun1()
        //调用 BaseInterface 的 fun1() 函数
        super<BaseInterface>.fun1()
    }
}

猜你喜欢

转载自blog.csdn.net/new_one_object/article/details/80042317