class Example // 從 Any 隱式繼承
Any 默認(rèn)提供了三個(gè)函數(shù):
equals()hashCode()toString()
注意:Any 不是 java.lang.Object。
如果一個(gè)類(lèi)要被繼承,可以使用 open 關(guān)鍵字進(jìn)行修飾。
open class Base(p: Int) // 定義基類(lèi)class Derived(p: Int) : Base(p)
構(gòu)造函數(shù)
子類(lèi)有主構(gòu)造函數(shù)
如果子類(lèi)有主構(gòu)造函數(shù), 則基類(lèi)必須在主構(gòu)造函數(shù)中立即初始化。
open class Person(var name : String, var age : Int){// 基類(lèi)}class Student(name : String, age : Int, var no : String, var score : Int) : Person(name, age) {}// 測(cè)試fun main(args: Array<String>) { val s = Student("Runoob", 18, "S12346", 89) println("學(xué)生名: ${s.name}") println("年齡: ${s.age}") println("學(xué)生號(hào): ${s.no}") println("成績(jī): ${s.score}")}
輸出結(jié)果:
學(xué)生名: Runoob年齡: 18學(xué)生號(hào): S12346成績(jī): 89
子類(lèi)沒(méi)有主構(gòu)造函數(shù)
如果子類(lèi)沒(méi)有主構(gòu)造函數(shù),則必須在每一個(gè)二級(jí)構(gòu)造函數(shù)中用 super 關(guān)鍵字初始化基類(lèi),或者在代理另一個(gè)構(gòu)造函數(shù)。初始化基類(lèi)時(shí),可以調(diào)用基類(lèi)的不同構(gòu)造方法。
class Student : Person { constructor(ctx: Context) : super(ctx) { } constructor(ctx: Context, attrs: AttributeSet) : super(ctx,attrs) { }}
實(shí)例
/**用戶基類(lèi)**/open class Person(name:String){ /**次級(jí)構(gòu)造函數(shù)**/ constructor(name:String,age:Int):this(name){ //初始化 println("-------基類(lèi)次級(jí)構(gòu)造函數(shù)---------") }}/**子類(lèi)繼承 Person 類(lèi)**/class Student:Person{ /**次級(jí)構(gòu)造函數(shù)**/ constructor(name:String,age:Int,no:String,score:Int):super(name,age){ println("-------繼承類(lèi)次級(jí)構(gòu)造函數(shù)---------") println("學(xué)生名: ${name}") println("年齡: ${age}") println("學(xué)生號(hào): ${no}") println("成績(jī): ${score}") }}fun main(args: Array<String>) { var s = Student("Runoob", 18, "S12345", 89)}
輸出結(jié)果:
-------基類(lèi)次級(jí)構(gòu)造函數(shù)----------------繼承類(lèi)次級(jí)構(gòu)造函數(shù)---------學(xué)生名: Runoob年齡: 18學(xué)生號(hào): S12345成績(jī): 89
重寫(xiě)
在基類(lèi)中,使用fun聲明函數(shù)時(shí),此函數(shù)默認(rèn)為final修飾,不能被子類(lèi)重寫(xiě)。如果允許子類(lèi)重寫(xiě)該函數(shù),那么就要手動(dòng)添加 open 修飾它, 子類(lèi)重寫(xiě)方法使用 override 關(guān)鍵詞:
/**用戶基類(lèi)**/open class Person{ open fun study(){ // 允許子類(lèi)重寫(xiě) println("我畢業(yè)了") }}/**子類(lèi)繼承 Person 類(lèi)**/class Student : Person() { override fun study(){ // 重寫(xiě)方法 println("我在讀大學(xué)") }}fun main(args: Array<String>) { val s = Student() s.study();}
輸出結(jié)果為:
我在讀大學(xué)
如果有多個(gè)相同的方法(繼承或者實(shí)現(xiàn)自其他類(lèi),如A、B類(lèi)),則必須要重寫(xiě)該方法,使用super范型去選擇性地調(diào)用父類(lèi)的實(shí)現(xiàn)。
open class A { open fun f () { print("A") } fun a() { print("a") }}interface B { fun f() { print("B") } //接口的成員變量默認(rèn)是 open 的 fun b() { print("b") }}class C() : A() , B{ override fun f() { super<A>.f()//調(diào)用 A.f() super<B>.f()//調(diào)用 B.f() }}fun main(args: Array<String>) { val c = C() c.f();}
C 繼承自 a() 或 b(), C 不僅可以從 A 或者 B 中繼承函數(shù),而且 C 可以繼承 A()、B() 中共有的函數(shù)。此時(shí)該函數(shù)在中只有一個(gè)實(shí)現(xiàn),為了消除歧義,該函數(shù)必須調(diào)用A()和B()中該函數(shù)的實(shí)現(xiàn),并提供自己的實(shí)現(xiàn)。
輸出結(jié)果為:
AB
屬性重寫(xiě)
屬性重寫(xiě)使用 override 關(guān)鍵字,屬性必須具有兼容類(lèi)型,每一個(gè)聲明的屬性都可以通過(guò)初始化程序或者getter方法被重寫(xiě):
open class Foo { open val x: Int get { …… }}class Bar1 : Foo() { override val x: Int = ……}
你可以用一個(gè)var屬性重寫(xiě)一個(gè)val屬性,但是反過(guò)來(lái)不行。因?yàn)関al屬性本身定義了getter方法,重寫(xiě)為var屬性會(huì)在衍生類(lèi)中額外聲明一個(gè)setter方法
你可以在主構(gòu)造函數(shù)中使用 override 關(guān)鍵字作為屬性聲明的一部分:
interface Foo { val count: Int}class Bar1(override val count: Int) : Fooclass Bar2 : Foo { override var count: Int = 0}
applixy
org***126.com
幾點(diǎn)補(bǔ)充:
1、子類(lèi)繼承父類(lèi)時(shí),不能有跟父類(lèi)同名的變量,除非父類(lèi)中該變量為 private,或者父類(lèi)中該變量為 open 并且子類(lèi)用 override 關(guān)鍵字重寫(xiě):
如上代碼片段中,子類(lèi) Student 主構(gòu)造方法的第一個(gè)字段 name 前邊加 var 關(guān)鍵字會(huì)報(bào)錯(cuò)。
2、子類(lèi)不一定要調(diào)用父類(lèi)和接口中共同擁有的同名的方法
引用文章中的話:“C 繼承自 a() 或 b(), C 不僅可以從 A 或則 B 中繼承函數(shù),而且 C 可以繼承 A()、B() 中共有的函數(shù)。此時(shí)該函數(shù)在中只有一個(gè)實(shí)現(xiàn),為了消除歧義,該函數(shù)必須調(diào)用A()和B()中該函數(shù)的實(shí)現(xiàn),并提供自己的實(shí)現(xiàn)?!?/p>
我試過(guò)了,不是必須調(diào)用 A() 和 B() 中該函數(shù)的實(shí)現(xiàn),代碼如下: