Kotlin類別的繼承

Fri, Nov 12, 2021 閱讀時間 1 分鐘

繼承(Inheritance)是物件導向中很重要的概念,我們可以為具有相似特性的子類別(derived class)共同繼承自一個父類別(base class),這樣不同的子類別都會有相同的特性(父類別的屬性和函數),又各自擁有自己的屬性和函數,可以達到差異化並減少重複撰寫相同的實作代碼

kotlin的類別預設是final(不能被繼承)的,除非我們顯式聲明開放(open)它可以被繼承,java的extends在kotlin是用冒號(:)來表示

open class Bird(a: Int) // 父類別要開放(open)繼承

// 如果父類別有主建構函數,則子類別必須在自己的主建構函數或次級建構函數先去呼叫初始化父類別
class Eagle(a: Int) : Bird(a)
class Swan : Bird {
    constructor(a: Int) : super(a) // 呼叫父類別的建構函數用super
    constructor(a: Int, b: Int) : this(a) // 呼叫同類別的建構函數用this
}

類別的屬性和函數如果要覆寫(override)它就必須開放(open)它,都需要顯式聲明出來,這點也是跟java不同的地方,我認為kotlin這樣做可以讓閱讀代碼的時候更加清楚,例如在父類別的初始化邏輯裡就要避免去使用open的成員,因為子類別如果有覆寫它是在父類別之後才會執行,就有可能導致程式發生不可預期的行為

// 類別要開放繼承,類別成員也才能開放被覆寫
open class Shape {
    // 覆寫屬性的方式跟函數一樣
    open val vertexCount: Int = 0

    // 開放子類別改寫
    open fun draw() {
        println("draw in the base class")
    }
}

class Rectangle : Shape() {
    // var可以覆寫val,反之則不行
    // 因為val只有getter,而var會有getter和setter
    override var vertexCount: Int = 4

    // 覆寫父類別的draw函數
    // override代表本身也是open的,所以如果不想再被繼承覆寫,前面可以加上final
    override fun draw() {
        super.draw() // 呼叫父類別的屬性和函數用super
        println("draw in the derived class")
    }
}