Kotlin Koans 學習筆記 —— Unit 4

Kotlin Koans 學習筆記 —— Unit 1
Kotlin Koans 學習筆記 —— Unit 2
Kotlin Koans 學習筆記 —— Unit 3

32 屬性

將自定義setter添加到’PropertyExample.propertyWithCounter’,以便每次’propertyWithCounter’被賦值時,'counter’屬性都會遞增。

class PropertyExample() {
    var counter = 0

    var propertyWithCounter: Int=0
        set(value) {
            counter++
            field = value //field是幕後字段
        }
}

關於本段請仔細閱讀:屬性與字段
如果不清楚屬性與字段的不同可以閱讀:Kotlin類和對象 (三)— 屬性和字段

33 懶加載

添加自定義getter以使’lazy’屬性懶加載。
在第一次訪問時,它應該通過調用’initializer()來初始化。
您可以根據需要添加任意數量的其他屬性。不要使用委託屬性!

class LazyProperty(val initializer: () -> Int) {
    var value: Int? = null
    val lazy: Int
        get() {
            if (value == null) { //類似於Java中實現單例模式時的玩法
                value = initializer()
            }
            return value!!
        }
}

34 委託

如果使用委託的話,我們可以這樣寫:

class LazyPropertyUsingDelegates(val initializer: () -> Int) {
    val lazyValue: Int by lazy(initializer)
    //by關鍵字用於實現屬性委託,lazy關鍵字是接受一個lambda表達式,
    // 在第一次加載字段的時候執行,並將結果賦予該字段,之後初始器不會再被調用。
}

如果你還沒接觸過 lazy 推薦閱讀:Kotlin 變量, 使用 Lazy 還是 Late

35 委託是如何工作的

委託表達式必須具有特殊的“get”和“set”方法。
您可以在下面看到他們的簽名作爲“ReadWriteProperty”接口的成員。
實現類’EffectiveDate’的成員,以便委派給它。
僅在’timeInMillis’屬性中存儲以毫秒爲單位的時間。
使用擴展函數’MyDate.toMillis’和’Long.toDate’。

關於屬性委託可以看這篇文章:Kotlin中理解委託屬性,並自定義委託

class EffectiveDate<R> : ReadWriteProperty<R, MyDate> {
    var timeInMillis: Long? = null

    operator override fun getValue(thisRef: R, property: KProperty<*>): MyDate = timeInMillis!!.toDate()
    operator override fun setValue(thisRef: R, property: KProperty<*>, value: MyDate) {
        timeInMillis = value.toMillis()
    }
}

我們來看一下測試代碼:

@Test fun testDate() {
    val d = D()
    /* Month numbering starts with 0 (0-Jan, 1-Feb, ... 11-Dec) */
    d.date = MyDate(2014, 1, 13)
    assertEquals(2014, d.date.year)
    assertEquals(1, d.date.month)
    assertEquals(13, d.date.dayOfMonth)
}

可以看到在題目中 D 類的屬性 date 通過關鍵字 by 委託給了 EffectiveDate 這個類,該類實現了 ReadWriteProperty 接口。在EffectiveDate 中當date 被賦值時,將會調用 setValue() 函數,我們將MyDate 裝換成 Long 來保存,在使用 date 屬性的成員屬性時,會調用 getValue() 方法,返回的是 MyDate 類型。

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