重拾Kotlin(8)-继承

作者: 业志陈 | 来源:发表于2019-05-23 22:47 被阅读5次

    一、继承

    在 Kotlin 中所有类都有一个共同的超类 Any ,对于没有超类声明的类来说它就是默认超类。需要注意的是, Any 并不是 java.lang.Object ,它除了 equals() 、 hashCode() 与 toString() 外没有其他属性或者函数

    要声明一个显式的超类,需要把父类名放到类头的冒号之后

    open class Base()
    
    class SubClass() : Base()
    

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

    如果派生类有一个主构造函数,其基类型必须直接或间接调用基类的主构造函数

    open class Base(val str: String)
    
    class SubClass(val strValue: String) : Base(strValue)
    
    class SubClass2 : Base {
    
        constructor(strValue: String) : super(strValue)
    
        constructor(intValue: Int) : super(intValue.toString())
    
        constructor(doubValue: Double) : this(doubValue.toString())
    
    }
    

    1.1、覆盖方法

    与 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 标记属性和方法是无意义的

    1.2、属性覆盖

    属性覆盖与方法覆盖类似。在超类中声明为 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 base1: Base = SubClass()
        println(base1.x) //100
        println(base1.y) //200
    
        val subClass = SubClass()
        println(subClass.x) //100
        println(subClass.y) //200
    
    }
    

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

    可以在主构造函数中使用 override 关键字作为属性声明的一部分

    open class Base {
        open val str: String = "Base"
    }
    
    class SubClass(override val str: String) : Base()
    
    fun main(args: Array<String>) {
        val base = Base()
        println(base.str) //Base
    
        val subClass = SubClass("leavesC")
        println(subClass.str) //leavesC
    }
    

    1.3、调用超类实现

    派生类可以通过 super 关键字调用其超类的函数与属性访问器的实现

    open class BaseClass {
        open fun fun1() {
            println("BaseClass fun1")
        }
    }
    
    class SubClass : BaseClass() {
    
        override fun fun1() {
            super.fun1()
        }
    
    }
    

    对于内部类来说,其本身就可以直接调用调用外部类的函数

    open class BaseClass2 {
        private fun fun1() {
            println("BaseClass fun1")
        }
    
        inner class InnerClass {
            fun fun2() {
                fun1()
            }
        }
    
    }
    

    但如果想要在一个内部类中访问外部类的超类,则需要通过由外部类名限定的 super 关键字来实现

    open class BaseClass {
        open fun fun1() {
            println("BaseClass fun1")
        }
    }
    
    class SubClass : BaseClass() {
    
        override fun fun1() {
            println("SubClass fun1")
        }
    
        inner class InnerClass {
    
            fun fun2() {
                super@SubClass.fun1()
            }
    
        }
    
    }
    
    fun main(args: Array<String>) {
        val subClass = SubClass()
        val innerClass = subClass.InnerClass()
        //BaseClass fun1
        innerClass.fun2()
    }
    

    如果一个类从它的直接超类和实现的接口中继承了相同成员的多个实现, 则必须覆盖这个成员并提供其自己的实现来消除歧义

    为了表示采用从哪个超类型继承的实现,使用由尖括号中超类型名限定的 super 来指定,如 super< BaseClass >

    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()
        }
    }
    

    重拾 Kotlin 系列文章目录: 重拾 Kotlin

    相关文章

      网友评论

        本文标题:重拾Kotlin(8)-继承

        本文链接:https://www.haomeiwen.com/subject/nzxwnqtx.html