Kotlin笔记(七)——委托属性(Delegated Properties)

Delegated Properties我姑且将其称为委托属性,因为实在不知道怎么翻译好,委托属性是一类特殊的Kotlin属性,先来看看最基本的委托属性。

class Dog1 {
    var name: String by Owner()
}

class Owner {

    private var mDogName: String = ""

    operator fun getValue(dog: Dog1, property: KProperty<*>): String {
        return mDogName
    }

    operator fun  setValue(dog: Dog1, property: KProperty<*>, s: String) {
        mDogName = s
    }
}


上面的例子中,我们定义了一个Dog类,其内有一个name属性,该属性使用了by关键字,将name属性委托给了Owner类,如果觉得抽象,可以这样理解,Dog有一个name属性,但是该属性的getter和setter则交给了另外一个类来负责实现,也就是说name属性的命运是由其他类来控制的,并非Dog类自己。


Owner类作为Dog类的name属性的被委托类,需要实现getValue和setValue两个operator方法,Kotlin通过operator方法指定一种运算,这里还涉及运算符重载,不再赘述。需要注意的是不要在getValue方法中使用dog.name,这样会出现上一篇文章中的无限递归调用。


上面就是Kotlin的委托属性,Kotlin官方文档给出了一个不错的概括:


1.对于只读属性(如val属性), 委托必须实现getValue方法,该方法的参数如下:


thisRef — 必须和属性所有者类型相同或者是属性所有者类型的超类,如上面的dog:Dog
property — 必须是KProperty<*>类型或者KProperty<*> 的超类
返回值——getValue方法必须返回和属性类型相同类型的返回值


2.对于可变属性(如var属性),委托必须实现setValue方法,该方法的参数如下:


thisRef — 与getValue相同
property — 与getValue相同

new value — 必须和属性相同类型或者是属性类型的超类


了解了委托属性的概念,Kotlin提供了几种现成的委托形式,先来看看懒加载属性。

class Dog2 {
    val name: String by lazy {
        println("First time call me")
        "Bebe"
    }
}

懒加载属性使用by lazy后跟lambda表达式的形式,lambda表达式内的代码只会在第一次获取属性值时被执行,之后不再执行,例如

val dog2 = Dog2()
println(dog2.name)
println(dog2.name)


输出结果为:

First time call me
Bebe
Bebe


下面看看可观察属性

class Dog3 {
    var name: String by Delegates.observable("Bebe") {
        prop, old, new ->
        println("My name changes from $old to $new")
    }
}

使用by Delegates.observable定义可观察属性,有两个参数,第一个参数是属性的默认值,第二个参数是一个高阶函数,该函数在属性被赋值后将被调用,我们可以做一些观测。下面是调用代码

val dog3 = Dog3()
println(dog3.name)
dog3.name = "BEBE"
println(dog3.name)


输出为

Bebe
My name changes from Bebe to BEBE
BEBE


另外还有一个Delegates.vetoable是在属性被赋值前被调用,这里不再赘述,感兴趣可以试试。


最后的一种委托属性可以帮助我们使用Map对常量属性进行初始化,Kotlin文档中介绍,这种委托主要适用于将JSON的数据组织为Map形式,然后初始化数据。

class Dog4(initValues: Map<String, String>) {
    val name by initValues
}

调用时

val dog4 = Dog4(mapOf("name" to "Bebe"))
println(dog4.name)

Map的key是属性的名称,value是赋值给属性的值。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值