委托可能是什么东东呢?kotlin中的委托可能不是太明白是啥意思,联想下生活中委托,是不是请某个人帮助我们来完成任务啊。
那么切入正题,Kotlin中委托就是指,有两个对象参与处理同一个请求,接受请求的对象将请求委托给另一个对象来处理。学过软件设计模式的有没有很熟悉,不就是代理模式吗?
Kotlin 直接支持委托模式,更加优雅,简洁。Kotlin 通过关键字 by 实现委托。
类委托
类委托:本类需要实现的方法/属性,借用其他已实现该方法/属性的对象作为自己的实现; 一旦使用了某类作为委托类,该类就能借用该委托类实现的方法/属性。
示例:
//定义一个抽象接口,包含一个属性和方法
interface Animal {
val color: String
fun getColor()
}
//建立一个类接受托(被委托的类),实现Animal接口的方法
class Dog : Animal {
override val color: String
get() = "黄色"
override fun getColor() {
println("${this.javaClass.name} is $color")
}
}
将被委托类作为构造器形参传入(常用)
//通过关键字 by 建立委托类
class Dog1(dog: Animal) : Animal by dog
新建委托类对象
class Dog2 : Animal by Dog()
新建委托类对象,并自己实现方法/属性
class Dog3 : Animal by Dog() {
override val color: String
get() = "白色"
override fun getColor() {
println("${this.javaClass.name} 是 $color")
}
}
执行示例:
fun main() {
val dog = Dog()
val dog1 = Dog1(dog)
dog1.getColor()
println(dog1.color)
val dog2 = Dog2()
dog2.getColor()
println(dog2.color)
val dog3 = Dog3()
dog3.getColor()
println(dog3.color)
}
结果:
by.Dog is 黄色
黄色
by.Dog is 黄色
黄色
by.Dog3 是 白色
白色
属性委托
属性委托:指的是一个类的某个属性值不是在类中直接进行定义,而是将其托付给一个代理类,从而实现对该类的属性统一管理。
属性委托语法格式:
val/var <属性名>: <类型> by <表达式>
- by 关键字之后的表达式就是委托,属性的 get() 方法(以及set() 方法)将被委托给这个对象的 getValue() 和 setValue() 方法。
- 属性委托不必实现任何接口, 但必须提供 getValue() 函数(对于 var属性,还需要 setValue() 函数)。
示例:该类需要包含 getValue() 方法和 setValue() 方法,且参数 dog为进行委托的类的对象,property为进行委托的属性的对象。
//定义一个Dog类 属性name委托Pet类实现
class Dog {
var name: String by Pet()
}
/**
* 定义一个被委托的类Pet,
* 为属性name创建了operator修饰的getValue和setValue方法 ;
* 该属性可被其他委托该类共享
* */
class Pet {
var nickName = ""
operator fun getValue(dog: Dog, property: KProperty<*>): String {
return nickName
}
operator fun setValue(dog: Dog, property: KProperty<*>, value: String) {
nickName = value
}
}
fun main(){
val dog = Dog()
dog.name = "大黄"
println(dog.name)
}
结果:
大黄
标准委托
Kotlin 的标准库中已经内置了很多工厂方法来实现属性的委托。
延迟属性 Lazy
lazy()
是一个函数, 接受一个 Lambda 表达式作为参数, 返回一个 Lazy <T> 实例的函数,返回的实例可以作为实现延迟属性的委托:第一次调用 get() 会执行已传递给 lazy() 的 lamda 表达式并记录结果, 后续调用 get() 只是返回记录的结果。
val lazyValue: String by lazy {
println("computed!") // 第一次调用输出,第二次调用不执行
"Hello"
}
fun main(args: Array<String>) {
println(lazyValue) // 第一次执行,执行两次输出表达式
println(lazyValue) // 第二次执行,只输出返回值
}
执行输出结果:
computed!
Hello
Hello
可观察属性 Observable
observable 可以用于实现观察者模式。
Delegates.observable() 函数接受两个参数: 第一个是初始化值, 第二个是属性值变化事件的响应器(handler)。
在属性赋值后会执行事件的响应器(handler),它有三个参数:被赋值的属性、旧值和新值:
import kotlin.properties.Delegates
class User {
var name: String by Delegates.observable("初始值") {
prop, old, new ->
println("旧值:$old -> 新值:$new")
}
}
fun main(args: Array<String>) {
val user = User()
user.name = "第一次赋值"
user.name = "第二次赋值"
}
结果:
旧值:初始值 -> 新值:第一次赋值
旧值:第一次赋值 -> 新值:第二次赋值
把属性储存在映射中
一个常见的用例是在一个映射(map)里存储属性的值。 这经常出现在像解析 JSON 或者做其他"动态"事情的应用中。 在这种情况下,你可以使用映射实例自身作为委托来实现委托属性。
class Site(map: MutableMap<String, Any?>) {
val name: String by map
val url: String by map
}
fun main() {
val map: MutableMap<String, Any?> = mutableMapOf(
"name" to "baidu",
"url" to "www.baidu.com"
)
val site = Site(map)
println(site.name)
println(site.url)
map["name"] = "Google"
map["url"] = "www.google.com"
println(site.name)
println(site.url)
}
结果:
baidu
www.baidu.com
Google
www.google.com
参考文章:
kotlin-in-chinese