继承

作者: 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()

回到目录

相关文章

  • 继承 继承

    属性拷贝 继承不单单能通过原型链实现,也能通过其他方式实现,属性拷贝就是其中一种方法。 通过属性拷贝也能实现继承子...

  • 继承(单继承,多继承)

    将共性的内容放在父类中,子类只需要关注自己特有的内容 python中所有的内容都是对象,所有的对象都直接或间接继承...

  • js继承方式

    类式继承 构造函数继承 组合继承 类式继承 + 构造函数继承 原型式继承 寄生式继承 寄生组合式继承 寄生式继承 ...

  • Python-学习之路-08 OOP -02

    单继承和多继承 单继承:每个类只能继承一个类 多继承:每个类可以继承多个类 单继承的多继承的优缺点 菱形继承/钻石...

  • 原型相关(二)

    1.继承 继承方式:接口继承(只继承方法签名)实现继承(继承实际的方法)ECMAScript只支持实现继承,并且主...

  • 继承

    继承的引入和概述 继承案例和继承的好处 继承的弊端 Java中继承的特点 继承的注意实现和什么时候使用继承 继承中...

  • Java面向对象三大特性之继承

    继承 一、继承的特点 Java只支持单继承单继承 多继承 单继承、多继承优缺点①单继承优点:提高了代码的复用性,让...

  • 7、面向对象的程序设计3(《JS高级》笔记)

    三、继承 许多OO语言都支持两种继承方式:接口继承和实现继承。接口继承只继承方法签名,而实现继承则继承实际方法。由...

  • 【重学前端】JavaScript中的继承

    JavaScript中继承主要分为六种:类式继承(原型链继承)、构造函数继承、组合继承、原型式继承、寄生式继承、寄...

  • js之继承

    文章主讲 JS 继承,包括原型链继承、构造函数继承、组合继承、寄生组合继承、原型式继承、 ES6 继承,以及 多继...

网友评论

      本文标题:继承

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