美文网首页
Kotlin继承与多态 (1)继承

Kotlin继承与多态 (1)继承

作者: 狼性代码人 | 来源:发表于2019-05-31 12:33 被阅读0次
  • 调用父类构造函数
    • 使用主构造函数
    • 使用此构造函数重载
    • 使用参数默认值调用构造函数
  • 重写成员属性和函数
    • 重写成员属性
    • 重写成员函数

  kotlin中类继承只能是单继承,但是却可以有多个接口实现,这一点与 Java 是一致的。kotlin中子类能够继承父类,那么父类需要声明为 open,在 kotlin 中默认类不能被继承,所以必须声明为 open

一、调用父类构造函数

  当子类实例化时,不仅需要初始化子类成员属性,也需要初始化父类成员属性,初始化父类成员属性需要调用父类构造函数。

open class Person(val name: String, 
                  val age: Int, 
                  val birthDate: Date) {    // 主构造函数

    constructor(name: String, age: Int): this(name, age, Date()) // 次构造函数

    override fun toString(): String {
        return ("Person [name=$name, age=$age, birthDate=$birthDate]")
    }
    
}
1、使用主构造函数
class Student(name: String,
              age: Int,
              birthDate: Date,
              val school: String): Person(name, age, birthDate) {   // 主构造函数

    constructor(name: String, age: Int, school: String): this(name, age, Date(), school) //1️⃣
    // constructor(name: String, age: Int, school: String): super(name, age, Date()) 2️⃣

    constructor(name: String, school: String): this(name, 18, school)

}

  子类继承父类时,子类中一旦声明了主构造函数,那么子类的此构造函数就不能直接调用父类构造函数,只能调用自己的主构造函数。例如上述代码第1️⃣行只能调用this(name, age, Date(), school) 而不能调用super(name, age, Date()),如第2️⃣行代码是编译不通过的。

2、使用此构造函数重载
class Student: Person {

    private var school: String? = null

    constructor(name: String,
                age: Int,
                birthDate: Date,
                school: String): super(name, age, birthDate) {  // 3️⃣
        this.school = school
    }

    constructor(name: String,
                school: String): super(name, 18) {  // 4️⃣
        this.school = school
    }

    constructor(name: String, age: Int, school: String): this(name, age, Date(), school)

}

  子类继承父类时,子类中如果没有声明主构造函数,则子类的次构造函数能直接调用父类构造函数,如代码第3️⃣行调用父类的主构造函数,代码第4️⃣行调用父类的次构造函数。

3、使用参数默认值调用构造函数

  一个类有多个构造函数时,多个构造函数之间构成了重载关系,kotlin 从语法角度是支持重载的,但更推荐采用参数默认值的方式。

class Student: Person {

    private var school: String? = null

    constructor(name: String,
                age: Int = 18,
                birthDate: Date = Date(),
                school: String): super(name, age, birthDate) {
        this.school = school
    }

}

  这段代码只有一个次构造函数,和4个参数,其中 agebirthDate 提供了默认值。这样声明相当于提供了4个构造函数。调用方式如下:

fun main(args: Array<String>) {
    val student1 = Student("小三", 20, Date(), "清华大学")
    val student2 = Student("小三", birthDate = Date(), school = "清华大学")
    val student3 = Student("小三", school = "清华大学")
    val student4 = Student("小三", age = 20, school = "清华大学")
}

  上面代码只有一个次构造函数,起始也可以有一个主构造函数。

class Student(name: String,
              age: Int = 18,
              birthDate: Date = Date(),
              school: String): Person(name, age, birthDate) {

    private var school: String? = null

    init {
        this.school = school
    }

}

二、重写成员属性和函数

子类继承父类后,子类中可能声明了与父类一样的成员属性和函数。

1、重写成语属性

  子类成员属性与父类一样,就会重写 (override) 父类中的成员属性,也就是屏蔽了父类成员属性。

open class ParentClass {

    open var x: Int = 10
}

class SubClass: ParentClass() {

    // 屏蔽父类x成员属性
    override var x: Int = 20

    fun printX() {
        
        println("x = $x")     // 访问的是SubClass的成员属性x
        
        println("super.x = ${super.x}") // 访问ParentClass的成员属性x
    }

}

fun main(args: Array<String>) {
    val subClass = SubClass()
    subClass.printX()
}

// x = 20
// super.x = 10

  子类继承父类时,子类可以重写父类总的成员属性,默认情况下属性是不能被重写的,它们需要声明为 open。另外,在子类中要重写属性需要有 override 关键字声明。
  注意:由于子类重写了父类的成员属性,所以会造成父类的被重写的成员属性可见性被屏蔽,所以要想在子类中让然使用父类被重写的属性,需要通过关键字 super. 调用。

2、重写成员函数

  如果子类函数完全与父类函数相同,即:相同的函数名、相同的参数列表和相同的返回类型,只是函数体不同,这称为子类重写父类函数。

open class ParentClass {

    open var x: Int = 0

    open fun setValue() {
        x = 10  // 6️⃣
    }
}

class SubClass: ParentClass() {

    // 屏蔽父类x成员属性
    override var x: Int = 0

    public override fun setValue() {
        x = 20

        super.setValue()
    }

    fun display() {
        println("x = $x")
        println("super.x = ${super.x}")
    }
}

fun main(args: Array<String>) {
    val subClass = SubClass()
    subClass.setValue()
    subClass.display()
}

2019-05-31 11:19:32.687 5085-5085/cn.ak.kot I/System.out: x = 10
2019-05-31 11:19:32.687 5085-5085/cn.ak.kot I/System.out: super.x = 0

  重写成员函数 与 重写成员属性 是一样,同样会屏蔽父类中被重写函数的可见性;父类中函数同样要声明为 open 的,因为默认是 final 的;子类重写函数也一样要使用关键字 override 修饰;在子类调用父类被重写的函数一样需要通过 super. 函数名。

  分析: main 函数中实例化的是 SubClass 类,所以 subClass.setValue() 调用的自然是 SubClasssetValue() 函数,而其中又通过 super.setValue() 调用了父类的 setValue(),但注意代码第6️⃣行中的 x 是对应 SubClassx 属性,因为 ParentClassx 属性被重载导致可见性被屏蔽。所以最终结果是super.x = 0

  注意:重写后的函数不能比原函数有更严格的可见性(可以相同)。

相关文章

  • Kotlin继承与多态 (1)继承

    调用父类构造函数使用主构造函数使用此构造函数重载使用参数默认值调用构造函数重写成员属性和函数重写成员属性重写成员函...

  • Kotlin继承与多态 (2)多态、is、as

    多态概念使用 is 和 !is 进行类型检查使用 as 和 as? 进行类型转换 一、多态概念 发生多态要有三个前...

  • 2020-05-16--Java--day09【继承、super

    1.继承 三大特征:封装,继承,多态 继承是多态的前提,没有继承就没有多态 继承的主要解决的问题就是:共性抽取 在...

  • PHP学习2

    六.继承与多态 1. 类的组合和继承(继承===“是、像”、“父与子”,组合===“需要”、“整体与局部”) 组合...

  • Python所学----python高级(中)

    一. 单继承 、多继承、多态,重写与父类 1.单继承、就是子类继承父类的属性与方法 2.多继承、就是子类继承多个父...

  • 继承、抽象类与接口

    第1节 继承 继承的概述 面向对象的三大特征:封装性、继承性、多态性。继承是多态的前提,如果没有继承,就没有多态。...

  • 面向对象

    继承与多态

  • Kotlin随笔,这次坚持不太监

    Kotlin中的类与继承 Java三大特性继承、多态、封装Java学习中首先学习的是类的构建,那么必然要学习构造方...

  • Kotlin学习之继承

    Kotlin学习之继承 @(Kotlin学习) Kotlin中的继承模式与Java中存在差异: Kotlin中所有...

  • 《Java8学习笔记》读书笔记(七)

    第6章 继承与多态 学习目标 了解继承的目的 了解继承与多态的关系 知道如何重写方法 认识java.lang.Ob...

网友评论

      本文标题:Kotlin继承与多态 (1)继承

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