Kotlin 繼承

Kotlin 中所有類都繼承該 Any 類,它是所有類的超類,對於沒有超型別宣告的類是預設超類:

class Example // 從 Any 隱式繼承

Any 預設提供了三個函式:

equals()

hashCode()

toString()

注意:Any 不是 java.lang.Object。

如果一個類要被繼承,可以使用 open 關鍵字進行修飾。

open class Base(p: Int)           // 定義基類

class Derived(p: Int) : Base(p)

建構函式

子類有主建構函式

如果子類有主建構函式, 則基類必須在主建構函式中立即初始化。

open class Person(var name : String, var age : Int){// 基類

}

class Student(name : String, age : Int, var no : String, var score : Int) : Person(name, age) {

}

// 測試
fun main(args: Array<String>) {
    val s =  Student("itread01", 18, "S12346", 89)
    println("學生名: ${s.name}")
    println("年齡: ${s.age}")
    println("學生號: ${s.no}")
    println("成績: ${s.score}")
}

輸出結果:

學生名: itread01
年齡: 18
學生號: S12346
成績: 89

子類沒有主建構函式

如果子類沒有主建構函式,則必須在每一個二級建構函式中用 super 關鍵字初始化基類,或者在代理另一個建構函式。初始化基類時,可以呼叫基類的不同構造方法。

class Student : Person {

    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("-------基類次級建構函式---------")
    }
}

/**子類繼承 Person 類**/
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("itread01", 18, "S12345", 89)
}

輸出結果:

-------基類次級建構函式---------
-------繼承類次級建構函式---------
學生名: itread01
年齡: 18
學生號: S12345
成績: 89

重寫

在基類中,使用fun宣告函式時,此函式預設為final修飾,不能被子類重寫。如果允許子類重寫該函式,那麼就要手動新增 open 修飾它, 子類重寫方法使用 override 關鍵詞:

/**使用者基類**/
open class Person{
    open fun study(){       // 允許子類重寫
        println("我畢業了")
    }
}

/**子類繼承 Person 類**/
class Student : Person() {

    override fun study(){    // 重寫方法
        println("我在讀大學")
    }
}

fun main(args: Array<String>) {
    val s =  Student()
    s.study();

}

輸出結果為:

我在讀大學

如果有多個相同的方法(繼承或者實現自其他類,如A、B類),則必須要重寫該方法,使用super範型去選擇性地呼叫父類的實現。

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{
    override fun f() {
        super<A>.f()//呼叫 A.f()
        super<B>.f()//呼叫 B.f()
    }
}

fun main(args: Array<String>) {
    val c =  C()
    c.f();

}

C 繼承自 a() 或 b(), C 不僅可以從 A 或則 B 中繼承函式,而且 C 可以繼承 A()、B() 中共有的函式。此時該函式在中只有一個實現,為了消除歧義,該函式必須呼叫A()和B()中該函式的實現,並提供自己的實現。

輸出結果為:

AB

屬性重寫

屬性重寫使用 override 關鍵字,屬性必須具有相容型別,每一個宣告的屬性都可以通過初始化程式或者getter方法被重寫:

open class Foo {
    open val x: Int get { …… }
}

class Bar1 : Foo() {
    override val x: Int = ……
}

你可以用一個var屬性重寫一個val屬性,但是反過來不行。因為val屬性本身定義了getter方法,重寫為var屬性會在衍生類中額外宣告一個setter方法

你可以在主建構函式中使用 override 關鍵字作為屬性宣告的一部分:

interface Foo {
    val count: Int
}

class Bar1(override val count: Int) : Foo

class Bar2 : Foo {
    override var count: Int = 0
}