继承

作者: codergege | 来源:发表于2018-11-22 22:11 被阅读0次

    回到目录
    项目源码 kotlin-class 项目


    Kotlin 中所有类都有一个共同的父类 Any. 如果没有显式声明父类, 都会隐式默认继承它

    class Example // Implicitly inherits from Any
    

    Any 并不是 java.lang.Object. 它除了 equals(), hashCode() 与 toString()
    外没有任何成员

    要显示声明父类, 可以把父类的构造函数放在类头的冒号后面:

    open class BaseA
    
    class DerivedA: BaseA()
    

    Kotlin 中的类默认都是不被基层的, 相当于 java 中的 final class. 如果想要被继承,
    可以在前面使用 open 关键字"打开封印".

    也可以用次构造函数:

    open class BaseB(val a: Int, val b: Int?, val c: Int) {
        constructor(a: Int, c: Int): this(a, null, c)
    }
    
    //  使用父类的用次构造函数也是可以的
    class DerivedB(a: Int, b: Int?, c: Int, val d: Int, val e: Int): BaseB(a, c)
    /*
    会生成这样的构造函数:
       public DerivedB(int a, @Nullable Integer b, int c, int d, int e) {
          super(a, c);
          this.d = d;
          this.e = e;
       }
     */
    

    派生类没有主构造函数, 使用次构造函数继承的情况:

    // 如果派生类没有主构造函数
    class DerivedBB: BaseB {
        // 因为属性必须初始化, 所以写上 getter
        // 没有必要写 setter, 会自动生成
        var d: Int
            get() = field
        var e: Int
            get() = field
        // 使用次构造函数继承父类, 得用 super 关键字
        constructor(a: Int, b: Int?, c:Int, d: Int, e:Int): super(a, b, c) {
            this.d = d
            this.e = e
        }
        constructor(a: Int, c: Int, d: Int, e: Int): super(a, c) {
            this.d = d
            this.e = e
        }
    

    重写方法(overriding)

    方法的重写也需要再父类中"打开封印", 因为方法也是默认 public final 的.

    open class BaseC {
        open fun funC() {
            println("funC")
        }
    }
    class DerivedC: BaseC() {
        override fun funC() {
    //        super.funC()
            println("重写后的 funC")
        }
    }
    
    fun main(args: Array<String>) {
        val derivedC = DerivedC()
        derivedC.funC()
    }
    

    标记为 override 后, 改方法本身就变成 open 的了, 可以用 final 再次禁止重写.

    重写属性

    跟重写方法一样, 重写属性也需要 open 关键字然后再 override:

    open class BaseD {
        open var d: Int = 0
        // 这个是没有 backing field 的
        open val dd get() = true
    }
    
    class DerivedD: BaseD() {
        override var d: Int = 1
        override var dd = false
    }
    

    调用父类方法及属性

    可以使用 super 调用父类的方法和属性的实现.

    open class BaseE {
        open fun funE() { println("BaseE.funE()") }
        open val e get() = 1
    }
    
    class DerivedE: BaseE() {
        override fun funE() {
            super.funE()
            println("DerivedE.funE()")
        }
        override val e get() = super.e + 1
    }
    

    内部类想调用外部内的父类方法属性可以用 super@Outer 语法实现:

    class DerivedE: BaseE() {
        override fun funE() {
            super.funE()
            println("DerivedE.funE()")
        }
        override val e get() = super.e + 1
        inner class InnerE {
            fun f() {
                super@DerivedE.funE()
                println(super@DerivedE.e)
            }
        }
    }
    

    继承规则

    如果一个类继承了多个直接超类(父类和接口), 并且这些父类中有同名的成员(属性或方法), 同名成员必须
    重写实现; 需要调用不同父类的同名成员, 使用 super<父类> 来区别.

    open class BaseF {
        open fun f() {
            println("BaseF.f()")
        }
        open val f get() = "BaseF.f"
    }
    interface IBaseG {
        // 接口中的方法和属性默认都是 open 的
        // 接口可以有实现代码
        fun f() {
            println("IBaseG.f()")
        }
        val f get() = "IBaseG.f"
    }
    
    class DerivedFG: BaseF(), IBaseG {
        override fun f() {
            super<BaseF>.f()
            super<IBaseG>.f()
        }
        override val f get() = super<BaseF>.f + super<IBaseG>.f
    }
    

    抽象类

    一个类中只要有一个抽象方法(abstract 标记的, 没有实现代码的方法), 那么这个类就
    是抽象类, 也必须用 abstract 标记.

    可以用抽象类的抽象方法去继承重写非抽象类的方法:

    open class BaseH {
        open fun f() {}
    }
    
    abstract class DerivedH : BaseH() {
        override abstract fun f()
    }
    

    伴生对象

    Kotlin 中没有 static 静态方法, 大部分情况下都推荐使用包级函数来代替.

    还有一种情况, 如果不用类实例对象来调用, 但又需要访问类内部(比如工厂方法), 那就
    需要在类中写一个"对象声明"(object declaration), 准确的说应该是需要声明一个"伴生
    对象"(companion object).

    class MyClass {
        // 可以省略伴生类的类名
        companion object {
            fun create(): MyClass = MyClass()
        }
    }
    

    然后可以这样去用(很像 static 方法):

    val instance = MyClass.create()
    

    回到目录

    相关文章

      网友评论

          本文标题:继承

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