Kotlin Koans 学习笔记 —— Unit 4

本文深入探讨Kotlin中的属性自定义setter与getter,演示如何实现属性的计数与懒加载,以及通过委托属性简化代码。同时,解析了属性与字段的区别,以及属性委托的工作原理。

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

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值