1. 程式人生 > >學習 Kotlin 03 - Data Class

學習 Kotlin 03 - Data Class

Data Class

data classkotlin 中的特殊類, 其特殊性表現在以下幾個方面:

  1. data class 的主建構函式至少需要一個引數;

  2. 主建構函式的所有引數都必須使用 valvar 修飾;

  3. data class 不能是抽象的, open 的, sealed 或內部類, 也就是說 data class 只能是 final 的;

  4. kotlin 1.1 之前, data class 還只能實現介面, 不能繼承類.

    kotlin 1.1 之後, data class 可以繼承其他類

在開發過程中, 我們經常需要使用一些類, 這些類的作用僅僅是用來存放資料, 而沒有多餘的函式. kotlin

中的 data class 正是為了這樣的作用而存在的.

以下是一個簡單的 data class , 該類表示在二維平面中的一個點:

// kotlin
data class Point(val x: Double, val y: Double)
  • 由於 data class 要求主建構函式至少要有一個引數 (第 1 點) , 且所有引數都必須使用 valvar 修飾 (第 2 點), 而在主建構函式中使用 valvar 修飾引數是 kotlin 建立類屬性的簡潔寫法, 因此 Point 類相當於有兩個屬性 x , y .

  • 呼叫 Point 建構函式時, 必須傳遞所有的引數 x

    , y . 如果想為 Point 類新增預設建構函式, 則需要新增輔助建構函式 (secondary constructor):

    data class Point(val x: Double, val y: Double) {
    constructor() : this(0.0, 0.0)
    }

    如果不想這麼麻煩, 最好的辦法是給主建構函式的引數新增預設值:

    data class Point(val x: Double = 0.0, val y: Double = 0.0)

拷貝函式 - copy

前面說過, data class 是存放資料的類, 那麼操作資料的時候就可能需要對資料進行拷貝, kotlin

預設為 data class 生成了拷貝函式 copy. 簡單呼叫 copy 函式將會產生一個和原來物件具有一樣屬性值的新物件:

val point = Point(1.0, 1.0) // (1.0, 1.0)
val point2 = point.copy()   // (1.0, 1.0)

如果想在拷貝的時候做一些修改, 可以直接給 copy 函式新增引數值, 使用命名引數列表的形式:

val point = Point(1.0, 1.0)         // (1.0, 1.0)
val point2 = point.copy()           // (1.0, 1.0)
val point3 = point.copy(y = 3.0)    // (1.0, 3.0)

componentN() 函式

除了 copy 函式, kotlin 還為 data class 生成 componentN() 函式, 其中 N 表示該 data class 的第 N 個屬性. 這使得在解構 data class 物件的時候非常方便, 可以使用 (com1, com2) = dataObjectdataObject 的兩個屬性分別賦值給 com1com2:

val point = Point(1.0, 3.0)
val (x, y) = point  // x = 1.0, y = 3.0

Kotlin 中的集合類 Map 的元素型別是 Map.Entry<K, V> , 但 Kotlin 本身類庫使用擴充套件函式 (Extension) 給 Map.Entry<K, V> 添加了 component1() , component2() 函式, 使得在遍歷 Map 時可以解構 Map.Entry<K, V> :

mapOf(1 to "one").forEach {(key, value) -> println("$key -> $value")}

Kotlin 標準庫中的 data class

在 Kotlin 類庫中已經為我們提供了表示二元組的類 Pair, 表示三元組的 Triple , 它們的屬性名分別是 first, second, third. 大多數情況下使用這兩個類或許已經足夠, 但有時候也需要我們自己編寫 data class , 使用更符合使用場景的類名和屬性名, 增強程式碼可讀性.