https://www.jianshu.com/p/a70ba6436e75/
https://www.jianshu.com/p/306bdc2bac3f
代理模式:为其他对象提供一种代理以控制其他对象对这个对象的访问。
委托属性的声明
定义一个委托属性的语法是 val/var <property name>: <Type> by <expression>,其中 by 后面的就是属性的委托。属性委托不用继承什么特别的接口,只要拥有用 operator 修饰的 getValue() 和 setValue() (适用 var)的函数就可以了。
by lazy的必须用val修饰
类委托
一个类中定义的方法实际是调用另一个类的对象的方法来实现的。
//创建接口
interface Base {
fun print()
}
//实现此接口的被委托的类
class BaseImpl(val x: Int) : Base {
override fun print() { print(x) }
}
//通过关键字 by 建立委托类
class Derived(b: Base) : Base by b
//测试
fun main(args: Array<String>) {
val b = BaseImpl(10)
Derived(b).print() // 输出 10
}
在 Derived 声明中,by 子句表示,将 b 保存在 Derived 的对象实例内部,而且编译器将会生成继承自 Base 接口的所有方法, 并将调用转发给 b。
属性委托
属性委托是指一个类的某个属性值不是在类中直接进行定义,而是将其托付给一个代理类,从而实现对该类的属性统一管理。
val/var 变量名:类型 by 表达式
by字之后的表达式就是委托,属性的get set方法将被委托给这个对象的setVaule getValue方法,属性委托不必实现任何接口,但必须提供getValue setValue函数。
import kotlin.reflect.KProperty
// 定义包含属性委托的类
class Example {
var p: String by Delegate()
}
// 委托的类
class Delegate {
//setValue getValue方法的修饰符 方法名 参数类型 只能这么写
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
return "$thisRef, 这里委托了 ${property.name} 属性"
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
println("$thisRef 的 ${property.name} 属性赋值为 $value")
}
}
fun main(args: Array<String>) {
val e = Example()
println(e.p) // 访问该属性,调用 getValue() 函数
e.p = "Runoob" // 调用 setValue() 函数
println(e.p)
}
输出结果为:
Example@433c675d, 这里委托了 p 属性
Example@433c675d 的 p 属性赋值为 Runoob
Example@433c675d, 这里委托了 p 属性
标准委托
Kotlin的标准库中已经内置了很多工厂方法来实现属性委托。
延迟属性lazy
lazy()是一个函数,接受一个lambda表达式作为参数,返回一个lazy<T>实例的函数,返回的实例可以作为实现延迟属性的委托:第一次调用get方法会执行已传递给lazy的lambda表达式并记录结果,后续调用get方法只是返回记录的结果。
val lazyValue: String by lazy {
println("computed!") // 第一次调用输出,第二次调用不执行
"Hello"
}
fun main(args: Array<String>) {
println(lazyValue) // 第一次执行,执行两次输出表达式
println("--------")
println(lazyValue) // 第二次执行,只输出返回值
}
执行输出结果:
computed!
Hello
--------
Hello
get方法是线程不安全的,lazy是线程安全的,
。。。后面还一个例子看文章。