美文网首页kotlin从基础到进阶
委托属性(Delegated Properties)

委托属性(Delegated Properties)

作者: duchao | 来源:发表于2018-04-25 22:01 被阅读3次

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

[plain]view plaincopy

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提供了几种现成的委托形式,先来看看懒加载属性。

[plain]view plaincopy

class Dog2 {  

    val name: String by lazy {  

        println("First time call me")  

        "Bebe"  

    }  

}  

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

[plain]view plaincopy

val dog2 = Dog2()  

println(dog2.name)  

println(dog2.name)  

输出结果为:

First time call me

Bebe

Bebe

下面看看可观察属性

[plain]view plaincopy

class Dog3 {  

    var name: String by Delegates.observable("Bebe") {  

        prop, old, new ->  

        println("My name changes from $old to $new")  

    }  

}  

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

[plain]view plaincopy

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形式,然后初始化数据。

[plain]view plaincopy

class Dog4(initValues: Map) {  

    val name by initValues  

}  

调用时

[plain]view plaincopy

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

println(dog4.name)  

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

转载于CSDN博主大鹏1987Kotlin笔记(七)——委托属性(Delegated Properties)

相关文章

网友评论

    本文标题:委托属性(Delegated Properties)

    本文链接:https://www.haomeiwen.com/subject/sfehtxtx.html