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