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("zaixian", 18, "S12346", 89) println("學生名: ${s.name}") println("年齡: ${s.age}") println("學生號: ${s.no}") println("成績: ${s.score}") }
輸出結果:
學生名: zaixian 年齡: 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("zaixian", 18, "S12345", 89) }
輸出結果:
-------基類次級構造函數--------- -------繼承類次級構造函數--------- 學生名: zaixian 年齡: 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 }