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
類型。