Kotlin繼承與多態(tài) (1)繼承

  • 調(diào)用父類構(gòu)造函數(shù)
    • 使用主構(gòu)造函數(shù)
    • 使用此構(gòu)造函數(shù)重載
    • 使用參數(shù)默認(rèn)值調(diào)用構(gòu)造函數(shù)
  • 重寫成員屬性和函數(shù)
    • 重寫成員屬性
    • 重寫成員函數(shù)

??kotlin中類繼承只能是單繼承,但是卻可以有多個(gè)接口實(shí)現(xiàn)冗懦,這一點(diǎn)與 Java 是一致的哲鸳。kotlin中子類能夠繼承父類甚纲,那么父類需要聲明為 open露泊,在 kotlin 中默認(rèn)類不能被繼承尤泽,所以必須聲明為 open签杈。

一、調(diào)用父類構(gòu)造函數(shù)

??當(dāng)子類實(shí)例化時(shí)沽一,不僅需要初始化子類成員屬性盖溺,也需要初始化父類成員屬性,初始化父類成員屬性需要調(diào)用父類構(gòu)造函數(shù)铣缠。

open class Person(val name: String, 
                  val age: Int, 
                  val birthDate: Date) {    // 主構(gòu)造函數(shù)

    constructor(name: String, age: Int): this(name, age, Date()) // 次構(gòu)造函數(shù)

    override fun toString(): String {
        return ("Person [name=$name, age=$age, birthDate=$birthDate]")
    }
    
}
1烘嘱、使用主構(gòu)造函數(shù)
class Student(name: String,
              age: Int,
              birthDate: Date,
              val school: String): Person(name, age, birthDate) {   // 主構(gòu)造函數(shù)

    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)

}

??子類繼承父類時(shí),子類中一旦聲明了主構(gòu)造函數(shù)蝗蛙,那么子類的此構(gòu)造函數(shù)就不能直接調(diào)用父類構(gòu)造函數(shù)蝇庭,只能調(diào)用自己的主構(gòu)造函數(shù)。例如上述代碼第1??行只能調(diào)用this(name, age, Date(), school) 而不能調(diào)用super(name, age, Date())捡硅,如第2??行代碼是編譯不通過的哮内。

2、使用此構(gòu)造函數(shù)重載
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)

}

??子類繼承父類時(shí)壮韭,子類中如果沒有聲明主構(gòu)造函數(shù)北发,則子類的次構(gòu)造函數(shù)能直接調(diào)用父類構(gòu)造函數(shù),如代碼第3??行調(diào)用父類的主構(gòu)造函數(shù)喷屋,代碼第4??行調(diào)用父類的次構(gòu)造函數(shù)琳拨。

3、使用參數(shù)默認(rèn)值調(diào)用構(gòu)造函數(shù)

??一個(gè)類有多個(gè)構(gòu)造函數(shù)時(shí)屯曹,多個(gè)構(gòu)造函數(shù)之間構(gòu)成了重載關(guān)系狱庇,kotlin 從語法角度是支持重載的,但更推薦采用參數(shù)默認(rèn)值的方式恶耽。

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
    }

}

??這段代碼只有一個(gè)次構(gòu)造函數(shù)僵井,和4個(gè)參數(shù),其中 agebirthDate 提供了默認(rèn)值驳棱。這樣聲明相當(dāng)于提供了4個(gè)構(gòu)造函數(shù)批什。調(diào)用方式如下:

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

??上面代碼只有一個(gè)次構(gòu)造函數(shù),起始也可以有一個(gè)主構(gòu)造函數(shù)社搅。

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
    }

}

二驻债、重寫成員屬性和函數(shù)

子類繼承父類后,子類中可能聲明了與父類一樣的成員屬性和函數(shù)形葬。

1合呐、重寫成語屬性

??子類成員屬性與父類一樣,就會(huì)重寫 (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

??子類繼承父類時(shí),子類可以重寫父類總的成員屬性,默認(rèn)情況下屬性是不能被重寫的拆祈,它們需要聲明為 open恨闪。另外,在子類中要重寫屬性需要有 override 關(guān)鍵字聲明放坏。
??注意:由于子類重寫了父類的成員屬性咙咽,所以會(huì)造成父類的被重寫的成員屬性可見性被屏蔽,所以要想在子類中讓然使用父類被重寫的屬性淤年,需要通過關(guān)鍵字 super. 調(diào)用钧敞。

2、重寫成員函數(shù)

??如果子類函數(shù)完全與父類函數(shù)相同麸粮,即:相同的函數(shù)名溉苛、相同的參數(shù)列表和相同的返回類型,只是函數(shù)體不同弄诲,這稱為子類重寫父類函數(shù)炊昆。

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

??重寫成員函數(shù) 與 重寫成員屬性 是一樣,同樣會(huì)屏蔽父類中被重寫函數(shù)的可見性威根;父類中函數(shù)同樣要聲明為 open 的,因?yàn)槟J(rèn)是 final 的视乐;子類重寫函數(shù)也一樣要使用關(guān)鍵字 override 修飾洛搀;在子類調(diào)用父類被重寫的函數(shù)一樣需要通過 super. 函數(shù)名。

??分析: main 函數(shù)中實(shí)例化的是 SubClass 類佑淀,所以 subClass.setValue() 調(diào)用的自然是 SubClasssetValue() 函數(shù)留美,而其中又通過 super.setValue() 調(diào)用了父類的 setValue(),但注意代碼第6??行中的 x 是對應(yīng) SubClassx 屬性伸刃,因?yàn)?ParentClassx 屬性被重載導(dǎo)致可見性被屏蔽谎砾。所以最終結(jié)果是super.x = 0

??注意:重寫后的函數(shù)不能比原函數(shù)有更嚴(yán)格的可見性(可以相同)捧颅。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末景图,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子碉哑,更是在濱河造成了極大的恐慌挚币,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,482評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件扣典,死亡現(xiàn)場離奇詭異妆毕,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)贮尖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門笛粘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事薪前∪笈” “怎么了?”我有些...
    開封第一講書人閱讀 152,762評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵序六,是天一觀的道長任连。 經(jīng)常有香客問我,道長例诀,這世上最難降的妖魔是什么随抠? 我笑而不...
    開封第一講書人閱讀 55,273評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮繁涂,結(jié)果婚禮上拱她,老公的妹妹穿的比我還像新娘。我一直安慰自己扔罪,他們只是感情好秉沼,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評(píng)論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著矿酵,像睡著了一般唬复。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上全肮,一...
    開封第一講書人閱讀 49,046評(píng)論 1 285
  • 那天敞咧,我揣著相機(jī)與錄音,去河邊找鬼辜腺。 笑死休建,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的评疗。 我是一名探鬼主播测砂,決...
    沈念sama閱讀 38,351評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼百匆!你這毒婦竟也來了砌些?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,988評(píng)論 0 259
  • 序言:老撾萬榮一對情侶失蹤加匈,失蹤者是張志新(化名)和其女友劉穎寄症,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體矩动,經(jīng)...
    沈念sama閱讀 43,476評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡有巧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評(píng)論 2 324
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了悲没。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片篮迎。...
    茶點(diǎn)故事閱讀 38,064評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡男图,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出甜橱,到底是詐尸還是另有隱情逊笆,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評(píng)論 4 323
  • 正文 年R本政府宣布岂傲,位于F島的核電站难裆,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏镊掖。R本人自食惡果不足惜乃戈,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望亩进。 院中可真熱鬧症虑,春花似錦、人聲如沸归薛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽主籍。三九已至习贫,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間千元,已是汗流浹背苫昌。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評(píng)論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留诅炉,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,511評(píng)論 2 354
  • 正文 我出身青樓屋厘,卻偏偏與公主長得像涕烧,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子汗洒,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容