Kotlin 數(shù)據(jù)類與密封類

2023-02-28 14:18 更新

數(shù)據(jù)類

Kotlin 可以創(chuàng)建一個(gè)只包含數(shù)據(jù)的類,關(guān)鍵字為 data:

data class User(val name: String, val age: Int)

編譯器會自動的從主構(gòu)造函數(shù)中根據(jù)所有聲明的屬性提取以下函數(shù):

  • equals() / hashCode()
  • toString() 格式如 "User(name=John, age=42)"
  • componentN() functions 對應(yīng)于屬性,按聲明順序排列
  • copy() 函數(shù)

如果這些函數(shù)在類中已經(jīng)被明確定義了,或者從超類中繼承而來,就不再會生成。

為了保證生成代碼的一致性以及有意義,數(shù)據(jù)類需要滿足以下條件:

  • 主構(gòu)造函數(shù)至少包含一個(gè)參數(shù)。
  • 所有的主構(gòu)造函數(shù)的參數(shù)必須標(biāo)識為val 或者 var ;
  • 數(shù)據(jù)類不可以聲明為 abstract, open, sealed 或者 inner;
  • 數(shù)據(jù)類不能繼承其他類 (但是可以實(shí)現(xiàn)接口)。

復(fù)制

復(fù)制使用 copy() 函數(shù),我們可以使用該函數(shù)復(fù)制對象并修改部分屬性, 對于上文的 User 類,其實(shí)現(xiàn)會類似下面這樣:

fun copy(name: String = this.name, age: Int = this.age) = User(name, age)

實(shí)例

使用 copy 類復(fù)制 User 數(shù)據(jù)類,并修改 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)

}

輸出結(jié)果為:

User(name=Jack, age=1)
User(name=Jack, age=2)

數(shù)據(jù)類以及解構(gòu)聲明

組件函數(shù)允許數(shù)據(jù)類在解構(gòu)聲明中使用:

val jane = User("Jane", 35)
val (name, age) = jane
println("$name, $age years of age") // prints "Jane, 35 years of age"

標(biāo)準(zhǔn)數(shù)據(jù)類

標(biāo)準(zhǔn)庫提供了 Pair 和 Triple 。在大多數(shù)情形中,命名數(shù)據(jù)類是更好的設(shè)計(jì)選擇,因?yàn)檫@樣代碼可讀性更強(qiáng)而且提供了有意義的名字和屬性。

密封類

密封類用來表示受限的類繼承結(jié)構(gòu):當(dāng)一個(gè)值為有限幾種的類型, 而不能有任何其他類型時(shí)。在某種意義上,他們是枚舉類的擴(kuò)展:枚舉類型的值集合 也是受限的,但每個(gè)枚舉常量只存在一個(gè)實(shí)例,而密封類 的一個(gè)子類可以有可包含狀態(tài)的多個(gè)實(shí)例。

聲明一個(gè)密封類,使用 sealed 修飾類,密封類可以有子類,但是所有的子類都必須要內(nèi)嵌在密封類中。

sealed 不能修飾 interface ,abstract class(會報(bào) warning,但是不會出現(xiàn)編譯錯誤)

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
}

使用密封類的關(guān)鍵好處在于使用 when 表達(dá)式 的時(shí)候,如果能夠 驗(yàn)證語句覆蓋了所有情況,就不需要為該語句再添加一個(gè) 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` 子句,因?yàn)槲覀円呀?jīng)覆蓋了所有的情況
}


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號