1.惰性加载
拉远站是一个函数,接受一个lambda表达式座位参数初始化函数,与前面实现的delegate类似,返回一个Lazy类型的实例,这个实例可以座位委托实现懒加载属性:
第一次调用get的时候,将会执行从lazy函数传入Lambda表达式,然后会记住这次执行的结果,以后所有对get()的调用都只会简单地返回以前记住的结果。
// 标准委托:惰性委托(lazy)
val lazyValue: String by lazy {
println("computed")
"hello"
}
fun main(args: Array<String>)
{
println(lazyValue)
println(lazyValue)
}
输出:
在默认情况下,惰性加载是执行同步的(synchronized)。属性值只在唯一一个线程内执行,然后所有线程都将得到同样的属性值。如果委托的初始化函数不需要同步,可以向lazy函数传入一个(LazyThreadSafetyMode.PUBLICATION)参数。想法如果你确信初始化函数只可能在一个线程中执行,那么可以使用(LazyThreadSafetyMode.NONE)模式,这种模式不会保持线程同步,因此不会带来这方面的损失。
2.可观察属性
所谓可观察属性就是当属性变化可以拦截其变化。
Delegates.observable() 需要俩个参数:一个初始值和一个修改者的 handler。每次我们分配属性时都会调用handler (在分配前执行)。它有三个参数:一个分配的属性,旧值,新值:
import kotlin.properties.Delegates
// 标准委托:可观察属性
// Delegates.observable
// 接受两个参数:1. 初始化值 2.属性值变化时响应器(Handler)
// 响应器: 1. prop 2. old 3. new
class User
{
var name:String by Delegates.observable("Mike")
{
prop,old,new ->
println("旧值:${old} 新值:${new}")
}
}
fun main(args: Array<String>)
{
val user = User()
user.name = "Bill"
user.name = "John"
}
输出:
3.阻止属性
如果你希望能够拦截属性的赋值操作,并且还能够“否决”赋值操作,那么不要使用observable函数,而应该使用vetoable函数。传递给vetoable函数的时间响应器会返回一个布尔类型的值,如果返回true,表示允许给属性复制,如果false,就会否决属性的赋值(仍然保留原来的值)
// 标准委托:阻止属性的赋值操作
// vetoable函数
class User1
{
var name:String by Delegates.vetoable("Mike") {
prop,old,new->
println("旧值:${old} 新值:${new}")
var result = true
// name属性值不能是Mary
if(new.equals("Mary"))
{
result = false
println("name属性值不能是Mary")
}
result
}
}
fun main(args: Array<String>)
{
val user = User1()
user.name = "Bill"
println(user.name)
user.name = "Mary"
println(user.name)
}
输出:
4. Map委托
Delegates.mapVal() 拥有一个 map 实例并返回一个可以从 map 中读其中属性的代理。在应用中有很多这样的例子,比如解析 JSON 或者做其它的一些 “动态”的事情:
class User2(var map: Map<String, Any>) {
val name: String by map //将map用作name属性的委托
val age: Int by map //将map用作age属性的委托
}
fun main(args: Array<String>) {
var map = mapOf("name" to "lulu","age" to 22)
val user = User2(map) //将map中的key-value直接映射到User类的属性上
println(user.age)
println(user.name)
}
输出:
5. MutableMap委托
如果要让上一小节的User2类的那么和age属性映射到可读写的委托,需要将这两个属性委托给 MutableMap
class User3(var map: MutableMap<String, Any>) {
var name: String by map //将map用作name属性的委托
var age: Int by map //将map用作age属性的委托
}
fun main(args: Array<String>) {
var map = mutableMapOf("name" to "lulu","age" to 22)
val user = User3(map) //将map中的key-value直接映射到User类的属性上
println(user.age)
println(user.name)
user.age = 88
user.name = "ddd"
println(user.age)
println(user.name)
}
输出:
我们可以看到。如果将属性委托给MutableMap,那么变化是双向的。无论是修改MutableMap中的值,还是User类的属性值,变化都是同步的。