Kotlin 筆記:密封類與代數數據類型

一、密封類

Kotlin 類開放性排序

  • 普通類(不加修飾符,不能繼承,默認是 final 的)
  • 密封類(sealed 修飾符,有條件繼承)
  • 開放類(open 修飾符,無條件繼承)

密封類的限制

  • 可以繼承,但只能在當前文件繼承

    • 在本類內繼承
    • 在類外被同級類繼承(不能在一個同級類的內部被繼承)
    sealed class A {
        class B: A() // OK, B is not sealed class
    }
    class C: A() // OK, B is not sealed class
    class D {
        class E:A() // not OK
    }
    
  • 不能實例化,因爲它的構造方法是私有的(它還是一個抽象類)

  • 它的子類如不聲明 sealed,則不是一個密封類

密封類的作用

一個更強大的枚舉。

枚舉類:對象數量固定。
密封類:子類數量固定。

它們都可以實現:
在用於 when 表達式判斷時,可以不用寫 else(在 when 沒有覆蓋到所有情況時報錯,只在 when 表達式用於返回一個值時生效)。

密封類強於枚舉類的地方:
枚舉類固定數量的是對象。所有的枚舉對象都是一個類,不好區分不同的行爲。
密封類固定數量的是子類。子類可以有自己的屬性、方法,更加靈活。
如:

sealed class Shape {
    class Circle(val radius: Double) : Shape()
    class Rectangle(val width: Double, val height: Double) : Shape()
    class Triangle(val base: Double, val height: Double) : Shape()
}

fun getArea(shape: Shape): Double = when (shape) {
    is Shape.Circle -> Math.PI * shape.radius * shape.radius
    is Shape.Rectangle -> shape.width * shape.height
    is Shape.Triangle -> shape.base * shape.height / 2.0
}

二、代數數據類型

代數數據類型

ADT(Algebraic Data Type),一種組合數據類型,即由其他數據類型組合成的類型。兩種常見的代數數據類型是積類型和類型

計數

一個類型取值的種類數。
如:
Boolean 是 2
Unit 是 1
String 是無限
Int 是無限

積類型

如 Boolean、Unit 的積類型是 BooleanUnit,它的計數是 2*1=2。

和類型

枚舉可以看作一種和類型,它的計數是枚舉子項(對象)的個數。
密封類也可以看作一種和類型,它的計數是子類的個數。

代數數據類型的好處

類型安全,即計數固定,所以 when 可以省略 else。

爲什麼要用密封類,而不是 open 類?

一個 open 類可以被繼承,那麼它的取值類型計數是可以變化的,比如第三方庫中的一個文件中聲明瞭一個類,寫了一個沒有 else 的 when。然後宿主中有個類繼承了它,那這個 when 就會出現問題。
而密封類就不會有這個問題,只有文件的編寫者才能創建一個新的子類,從而改變它的取值類型計數。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章