Kotlin之继承

作者: 芒果味的你呀 | 来源:发表于2017-11-26 19:11 被阅读119次

    一、Kotlin 中所有类都继承该 Any 类,它是所有类的超类,对于没有超类型声明的类是默认超类。Any默认提供了三个函数:equals()、hashCode()、toString()

    二、关于构造函数

    • 如果一个子类有主构造函数, 则基类(父类)必须在主构造函数中立即初始化。
    //如果一个类要被继承,可以使用 open 关键字进行修饰。
    open class Base(p: Int)//Base为基类
    class Derived(p: Int) : Base(p)
    
    • 如果类没有主构造函数,那么每个次构造函数必须使用 super 关键字初始化其基类型,或委托给另一个构造函数做到这一点。 注意,在这种情况下,不同的次构造函数可以调用基类型的不同的构造函数:
    class MyView : View {
        constructor(ctx: Context) : super(ctx)
        constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs)
    }
    
    //基类
    open class Person(name:String){
    //次级构造函数
        constructor(name:String,age:Int):this(name){
            //初始化
            println("基类次级构造函数")
        }
    }
    class Student:Person{    
    //次级构造函数constructor(name:String,age:Int,no:String,score:Int):super(name,age){
            println("继承类次级构造函数")
            println("学生名: ${name}")
            println("年龄: ${age}")
            println("学生号: ${no}")
            println("成绩: ${score}")
        }
    }
    
    fun main(args: Array<String>) {
        var s =  Student("芒果", 21, "111111", 100)
    }
    //输出:
    基类次级构造函数
    继承类次级构造函数
    学生名: 芒果
    年龄: 21
    学生号: 111111
    成绩: 100
    

    三、关于修饰词

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

    四、覆盖方法(方法重写)

    • Kotlin 力求清晰显式。与 Java 不同,Kotlin 需要显式标注可覆盖的成员(我们称之为开放)和覆盖后的成员,在基类中,使用fun声明函数时,此函数默认为final修饰,不能被子类重写。如果允许子类重写该函数,那么就要手动添加 open 修饰它, 子类重写方法使用 override 关键词。
    open class Base {
        open fun v() {}
        fun nv() {}
    }
    class Derived() : Base() {
        override fun v() {}
    }
    

    Derived.v() 函数上必须加上 override标注。如果没写,编译器将会报错。 如果函数没有标注 open 如 Base.nv(),则子类中不允许定义相同签名的函数, 不论加不加 override。在一个 final 类中(没有用 open 标注的类),开放成员是禁止的。
    标记为 override 的成员本身是开放的,也就是说,它可以在子类中覆盖。如果你想禁止再次覆盖,使用 final 关键字:

    open class AnotherDerived() : Base() {
        final override fun v() {}
    }
    

    五、覆盖属性(属性重写)

    属性覆盖与方法覆盖类似;在超类中声明然后在派生类中重新声明的属性必须以override开头
    • 能被覆盖的属性必须具有初始化器或者具有 getter 方法
    open class Base {
        open val x: Int get { …… }//具有初始化程序
    }
    
    class Derived : Base() {
        override val x: Int = ……//重新声明的属性必须以override开头
    }
    
    • 并且它们必须具有兼容的类型。比如说用一个var属性重写一个val属性。但是却不能用一个val属性重写一个var属性。原因是:val不可变 var可变。val具有getter属性,用var去复写的时候就是在基础上增加setter、方法。
    open class Base {
        open val x: Int //具有getter
    }
    
    class Derived : Base() {
        override var x: Int =1//用var覆写
    }
    

    六、调用超类的实现

    • 派生类中的代码可以使用 super 关键字调用其超类的函数与属性访问器的实现:
    open class Base {
        open fun f() { println("超类.....") }
        open val x: Int get() = 1
    }
    
    class Derived :Base() {
        override fun f() { 
            super.f()//用super调用超类函数
            println("派生类") 
        }
        override val x: Int get() = super.x + 1//用super调用超类属性
    }
    
    • 在一个内部类中访问外部类的超类,可以通过由外部类名限定的 super 关键字来实现:super@Outer:
    open class Base {
        open fun f() { println("超类.....") }
        open val x: Int get() = 1
    }
    class Derived : Base() {
        override fun f() { /* …… */ }
        override val x: Int get() = 0
        
        inner class InnerClass {
            fun g() {
                super@Derived.f() // 调用 Base 实现的 f()
                println(super@Derived.x) // 使用 Base 实现的 x 的 getter
            }
        }
    }
    

    七、覆盖规则

    在 Kotlin 中,实现继承由下述规则规定:如果一个类从它的直接超类继承相同成员的多个实现, 它必须覆盖这个成员并提供其自己的实现(也许用继承来的其中之一)。 为了表示采用从哪个超类型继承的实现,我们使用由尖括号中超类型名限定的 super,如 super<Base>:

    //同时继承 A 和 B 没问题,并且 a() 和 b() 也没问题因为 C 只继承了每个函数的一个实现。
     // 但是 f() 由 C 继承了两个实现,所以我们必须在 C 中覆盖 f() 并且提供我们自己的实现来消除歧义。
    open class A {
        open fun f() { print("A") }
        fun a() { print("a") }
    }
    
    interface B {
        fun f() { print("B") } // 接口成员默认就是“open”的
        fun b() { print("b") }
    }
    
    class C() : A(), B {
        // 编译器要求覆盖 f():
        override fun f() {
            super<A>.f() // 调用 A.f()
            super<B>.f() // 调用 B.f()
      }
    }
    

    相关文章

      网友评论

        本文标题:Kotlin之继承

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