Kotlin 數據類與密封類
阿新 • • 發佈:2019-04-29
() clas strac tostring 對象 nts 而且 表示 我們
數據類
Kotlin 可以創建一個只包含數據的類,關鍵字為 data:
data class User(val name: String, val age: Int)
編譯器會自動的從主構造函數中根據所有聲明的屬性提取以下函數:
equals()
/hashCode()
toString()
格式如"User(name=John, age=42)"
componentN() functions
對應於屬性,按聲明順序排列copy()
函數
如果這些函數在類中已經被明確定義了,或者從超類中繼承而來,就不再會生成。
為了保證生成代碼的一致性以及有意義,數據類需要滿足以下條件:
-
主構造函數至少包含一個參數。
-
所有的主構造函數的參數必須標識為
val
或者var
; -
數據類不可以聲明為
abstract
,open
,sealed
或者inner
; -
數據類不能繼承其他類 (但是可以實現接口)。
復制
復制使用 copy() 函數,我們可以使用該函數復制對象並修改部分屬性, 對於上文的 User 類,其實現會類似下面這樣:
fun copy(name: String = this.name, age: Int = this.age) = User(name, age)
實例
使用 copy 類復制 User 數據類,並修改 age 屬性:
data class User(val name: String, val age: Int)
fun main(args: Array<String>) {
val jack = User(name = "Jack", age = 1)
val olderJack = jack.copy(age = 2)
println(jack)
println(olderJack)
}
輸出結果為:
User(name=Jack, age=1)
User(name=Jack, age=2)
數據類以及解構聲明
組件函數允許數據類在解構聲明中使用:
val jane = User("Jane", 35)
val (name, age) = jane
println("$name, $age years of age") // prints "Jane, 35 years of age"
標準數據類
標準庫提供了 Pair 和 Triple 。在大多數情形中,命名數據類是更好的設計選擇,因為這樣代碼可讀性更強而且提供了有意義的名字和屬性。
密封類
密封類用來表示受限的類繼承結構:當一個值為有限幾種的類型, 而不能有任何其他類型時。在某種意義上,他們是枚舉類的擴展:枚舉類型的值集合 也是受限的,但每個枚舉常量只存在一個實例,而密封類 的一個子類可以有可包含狀態的多個實例。
聲明一個密封類,使用 sealed 修飾類,密封類可以有子類,但是所有的子類都必須要內嵌在密封類中。
sealed 不能修飾 interface ,abstract class(會報 warning,但是不會出現編譯錯誤)
sealed class Expr
data class Const(val number: Double) : Expr()
data class Sum(val e1: Expr, val e2: Expr) : Expr()
object NotANumber : Expr()
fun eval(expr: Expr): Double = when (expr) {
is Const -> expr.number
is Sum -> eval(expr.e1) + eval(expr.e2)
NotANumber -> Double.NaN
}
使用密封類的關鍵好處在於使用 when 表達式 的時候,如果能夠 驗證語句覆蓋了所有情況,就不需要為該語句再添加一個 else 子句了。
fun eval(expr: Expr): Double = when(expr) {
is Expr.Const -> expr.number
is Expr.Sum -> eval(expr.e1) + eval(expr.e2)
Expr.NotANumber -> Double.NaN
// 不再需要 `else` 子句,因為我們已經覆蓋了所有的情況
}
Kotlin 數據類與密封類