繼承

回到目錄
項目源碼 kotlin-class 項目


Kotlin 中所有類都有一個共同的父類 Any. 如果沒有顯式聲明父類, 都會隱式默認繼承它

class Example // Implicitly inherits from Any

Any 并不是 java.lang.Object. 它除了 equals(), hashCode() 與 toString()
外沒有任何成員

要顯示聲明父類, 可以把父類的構(gòu)造函數(shù)放在類頭的冒號后面:

open class BaseA

class DerivedA: BaseA()

Kotlin 中的類默認都是不被基層的, 相當于 java 中的 final class. 如果想要被繼承,
可以在前面使用 open 關(guān)鍵字"打開封印".

也可以用次構(gòu)造函數(shù):

open class BaseB(val a: Int, val b: Int?, val c: Int) {
    constructor(a: Int, c: Int): this(a, null, c)
}

//  使用父類的用次構(gòu)造函數(shù)也是可以的
class DerivedB(a: Int, b: Int?, c: Int, val d: Int, val e: Int): BaseB(a, c)
/*
會生成這樣的構(gòu)造函數(shù):
   public DerivedB(int a, @Nullable Integer b, int c, int d, int e) {
      super(a, c);
      this.d = d;
      this.e = e;
   }
 */

派生類沒有主構(gòu)造函數(shù), 使用次構(gòu)造函數(shù)繼承的情況:

// 如果派生類沒有主構(gòu)造函數(shù)
class DerivedBB: BaseB {
    // 因為屬性必須初始化, 所以寫上 getter
    // 沒有必要寫 setter, 會自動生成
    var d: Int
        get() = field
    var e: Int
        get() = field
    // 使用次構(gòu)造函數(shù)繼承父類, 得用 super 關(guān)鍵字
    constructor(a: Int, b: Int?, c:Int, d: Int, e:Int): super(a, b, c) {
        this.d = d
        this.e = e
    }
    constructor(a: Int, c: Int, d: Int, e: Int): super(a, c) {
        this.d = d
        this.e = e
    }

重寫方法(overriding)

方法的重寫也需要再父類中"打開封印", 因為方法也是默認 public final 的.

open class BaseC {
    open fun funC() {
        println("funC")
    }
}
class DerivedC: BaseC() {
    override fun funC() {
//        super.funC()
        println("重寫后的 funC")
    }
}

fun main(args: Array<String>) {
    val derivedC = DerivedC()
    derivedC.funC()
}

標記為 override 后, 改方法本身就變成 open 的了, 可以用 final 再次禁止重寫.

重寫屬性

跟重寫方法一樣, 重寫屬性也需要 open 關(guān)鍵字然后再 override:

open class BaseD {
    open var d: Int = 0
    // 這個是沒有 backing field 的
    open val dd get() = true
}

class DerivedD: BaseD() {
    override var d: Int = 1
    override var dd = false
}

調(diào)用父類方法及屬性

可以使用 super 調(diào)用父類的方法和屬性的實現(xiàn).

open class BaseE {
    open fun funE() { println("BaseE.funE()") }
    open val e get() = 1
}

class DerivedE: BaseE() {
    override fun funE() {
        super.funE()
        println("DerivedE.funE()")
    }
    override val e get() = super.e + 1
}

內(nèi)部類想調(diào)用外部內(nèi)的父類方法屬性可以用 super@Outer 語法實現(xiàn):

class DerivedE: BaseE() {
    override fun funE() {
        super.funE()
        println("DerivedE.funE()")
    }
    override val e get() = super.e + 1
    inner class InnerE {
        fun f() {
            super@DerivedE.funE()
            println(super@DerivedE.e)
        }
    }
}

繼承規(guī)則

如果一個類繼承了多個直接超類(父類和接口), 并且這些父類中有同名的成員(屬性或方法), 同名成員必須
重寫實現(xiàn); 需要調(diào)用不同父類的同名成員, 使用 super<父類> 來區(qū)別.

open class BaseF {
    open fun f() {
        println("BaseF.f()")
    }
    open val f get() = "BaseF.f"
}
interface IBaseG {
    // 接口中的方法和屬性默認都是 open 的
    // 接口可以有實現(xiàn)代碼
    fun f() {
        println("IBaseG.f()")
    }
    val f get() = "IBaseG.f"
}

class DerivedFG: BaseF(), IBaseG {
    override fun f() {
        super<BaseF>.f()
        super<IBaseG>.f()
    }
    override val f get() = super<BaseF>.f + super<IBaseG>.f
}

抽象類

一個類中只要有一個抽象方法(abstract 標記的, 沒有實現(xiàn)代碼的方法), 那么這個類就
是抽象類, 也必須用 abstract 標記.

可以用抽象類的抽象方法去繼承重寫非抽象類的方法:

open class BaseH {
    open fun f() {}
}

abstract class DerivedH : BaseH() {
    override abstract fun f()
}

伴生對象

Kotlin 中沒有 static 靜態(tài)方法, 大部分情況下都推薦使用包級函數(shù)來代替.

還有一種情況, 如果不用類實例對象來調(diào)用, 但又需要訪問類內(nèi)部(比如工廠方法), 那就
需要在類中寫一個"對象聲明"(object declaration), 準確的說應(yīng)該是需要聲明一個"伴生
對象"(companion object).

class MyClass {
    // 可以省略伴生類的類名
    companion object {
        fun create(): MyClass = MyClass()
    }
}

然后可以這樣去用(很像 static 方法):

val instance = MyClass.create()

回到目錄

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末齿拂,一起剝皮案震驚了整個濱河市召庞,隨后出現(xiàn)的幾起案子泰讽,更是在濱河造成了極大的恐慌初坠,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件敦捧,死亡現(xiàn)場離奇詭異蚁飒,居然都是意外死亡,警方通過查閱死者的電腦和手機咳榜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來爽锥,“玉大人贿衍,你說我怎么就攤上這事【群蓿” “怎么了?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵释树,是天一觀的道長肠槽。 經(jīng)常有香客問我,道長奢啥,這世上最難降的妖魔是什么秸仙? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮桩盲,結(jié)果婚禮上寂纪,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好捞蛋,可當我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布孝冒。 她就那樣靜靜地躺著,像睡著了一般拟杉。 火紅的嫁衣襯著肌膚如雪庄涡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天搬设,我揣著相機與錄音穴店,去河邊找鬼。 笑死拿穴,一個胖子當著我的面吹牛泣洞,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播默色,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼球凰,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了该窗?” 一聲冷哼從身側(cè)響起弟蚀,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎酗失,沒想到半個月后义钉,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡规肴,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年捶闸,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拖刃。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡删壮,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出兑牡,到底是詐尸還是另有隱情央碟,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布均函,位于F島的核電站亿虽,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏苞也。R本人自食惡果不足惜洛勉,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望如迟。 院中可真熱鬧收毫,春花似錦攻走、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至引润,卻和暖如春巩趁,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背淳附。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工议慰, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人奴曙。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓别凹,卻偏偏與公主長得像,于是被迫代替她去往敵國和親洽糟。 傳聞我的和親對象是個殘疾皇子炉菲,可洞房花燭夜當晚...
    茶點故事閱讀 44,724評論 2 354