Kotlin之類繼承結構

weixin_34290000發表於2019-01-10

介面

使用interface關鍵字來宣告一個介面

interface Clickable{
    fun click()
}

接下來實現這個介面

class Button : Clickable{
    override fun click() = println("I was clicked")
}

Kotlin中使用冒號代替了Java中的extendsimplements關鍵字。和Java一樣,一個類可以實現多個任意介面,但只能繼承一個類

與Java中的@Override註解類似,override修飾符用來標註被重寫的父類的介面的方法和屬性。

介面可以有一個預設的實現,當然也可以在子類中重新定義showOff函式的實現

interface Clickable{
    fun click()
    fun showOff() = println("I'm clickable!") //帶預設實現的方法
}

定義另一個實現了同樣方法的介面

interface Focusable{
    fun setFocus(b:Boolean) = println("I ${if (b) "got" else "lose"} focus")
    fun showOff() = println("I'm focusable!")
}

然後在一個子類中同時實現這兩個介面,它們每一個都包含了帶預設實現的showOff方法,那麼子類中你必須要實現這個方法,在Java中可以把基類的名字放在super關鍵字的前面;但是在Kotlin中需要把基類的名字放在尖括號中

class Button2 : Clickable,Focusable{
override fun showOff() {
    super<Clickable>.showOff()
    super<Focusable>.showOff()
}
override fun click() {}

}

注意:在Java中實現Kotlin的介面,Java並不支援介面中的預設方法,子類必須實現方法體

open、final和abstract修飾符:預設為final

宣告一個帶openopen

open class RichButton : Clickable{ //這個類是open的:其他類可以繼承它
    override fun click() {}//這個函式重寫了一個open函式並且它本身同樣是open的
    fun disable(){} //這個函式是final的:不能在子類中重寫它
    open fun animate(){}//這個函式是open的:可以在子類中重寫它
}

注意:如果你重寫了一個基類或者介面的成員,重寫了的成員同樣預設是open的。如果你想阻止你類的子類重寫你的實現,可以顯示地將重寫的成員標註為final

open class RichButton: Clickable {
    final override fun click(){}
}

抽象類

在Kotlin中,與Java一樣,可以將一個類宣告成abstract的,這種類不能被例項化。並且它內部的抽象成員始終是open的,因此不需要顯示地使用open修飾符

abstract class Animated{
    abstract fun animate()
    open fun stopAnimating(){}
    fun animateTwice(){}
}

修飾符

  • 訪問修飾符

    普通類中成員預設為final;介面、抽象類中成員預設為open;若子類繼承的父類方法為open,那麼子類重寫後的方法也為open
修飾符 相關成員 評註
final 不能被重寫 類中成員預設使用
open 可以被重寫 需要明確的表明
abstract 必須被重寫 只能在抽象類中使用;抽象成員不能有實現
override 重寫父類或介面中的成員 如果沒有使用final表明,重寫的成員預設是開放的
  • 可見性修飾符(預設為public)
修飾符 類成員 頂層宣告
public(預設) 所有地方可見 所有地方可見
internal 模組中可見 模組中可見
protected 子類中可見 ------------
private 類中可見 檔案中可見

內部類和巢狀類

Kotlin沒有顯示的巢狀類與Java中的static巢狀類一樣,要把它變成內部類來持有一個外部類的引用要用inner,下面是Java和Kotlin在這個行為上的不同:

類A在另一個類B中宣告 在Java中 在Kotlin中
巢狀類(不儲存外部類的引用) static class A class A
內部類(儲存外部類的引用) class A inner class A

密封類:定義受限的類繼承結構

在使用when表示式時,Kotlin編譯期會強制檢查預設選項。所以不得不新增一個預設的分支。Kotlin為這個問題提供了一個解決方案:sealed類。為父類新增一個sealed修飾符,對可能建立的子類做出嚴格的限制,所有的直接子類都必須巢狀在父類中

 sealed class Expr  //將基類標記成密封的,sealed修飾符隱含的是open的
{
    class Num(val value:Int) : Expr()   //將所有可能的類作為巢狀類
    class Sum(val left:Expr,val right:Expr) : Expr()
}

fun simplifyEval2(e:Expr):Int =
    when(e){// “when”表示式涵蓋了所有可能的情況,所以不再需要“else”分支
       is Expr.Num ->
            e.value
       is Expr.Sum ->
            simplifyEval2(e.left) + simplifyEval2(e.right)
    }

相關文章