目录
摘要
类的委托,属性的委托,Lazy Properties,Observable Properties,Not Null,Map Val
Delegate
类的委托
类的委托使用 by 语句
。
创建接口和子类
interface Base {
fun println()
}
class BaseImpl(val x: Int) : Base {
override fun println() {
println(x)
}
}
建立委托类
class Derived(b: Base) : Base by b
以上 Derived 类
创建了所有来自 Base 的方法
,并且委托一个传入的 Base 的对象
执行这些方法。
使用委托类
val b = BaseImpl(19)
b.println() // 19
Derived(b).println() // 19
属性的委托
创建被委托类
class Delegate {
fun get(thisRef: Any?, prop: PropertyMetadata): String {
return "$thisRef, thank you for delegating '${prop.name}}' to me!"
}
fun set(thisRef: Any?, prop: PropertyMetadata, value: String) {
println("$value has been assigned to '${prop.name} in $thisRef.'")
}
}
创建委托类
class Example {
var p: String by Delegate()
}
使用委托
val e = Example()
println(e.p)
e.p = "NEW"
内置属性委托
分类
Kotlin API 中有两种标准的属性委托方法,一种是 lazy properties,一种是 observable properties。
Lazy Properties
- Lazy Properties 在第一次被访问时才会获取值。
- Lazy Properties 是通过 lazy 方法来实现的。
- lazy 方法接收一个Lambda 表达式,在第一次执行时会计算 Lambda 的值然后存储起来,之后访问的话会直接取得保存的值,而不会重新计算。
val lazy: String by lazy {
println("computed!")
"Hello ${System.currentTimeMillis()}"
}
println("lazy is ${lazy}")
println("lazy is ${lazy}")
lazy 是非线程安全的,线程安全的版本见下面的例子
val blockLazy: String by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
println("computed2!")
"Hello2 ${System.currentTimeMillis()}"
}
Observable Properties
- Observable Properties 被存储在一个 Map 中,而不是单独的属性。
- Observable Properties 可以设置监听值改变事件的监听器。
- Observable Properties 是通过 observable()方法实现的。
- observable()方法接收两个参数,第一个为初始值,第二个为监听的回调Handler,该 Handler 接收三个参数:被设置的属性,旧值,新值。
class User {
var name: String by Delegates.observable("<no name>") {
d, old, new ->
println("$old -> $new")
}
}
val user = User()
user.name = "first"
user.name = "second"
也可以使用 vetoable()
代替 observable()
,该方法功能类似,但是返回布尔值,用以表示这次设置是否有效。
class User {
var age: Int by Delegates.vetoable(0) {
d, old, new ->
println("$old -> $new")
if (new < 20) true else false
}
}
val user = User()
user.age = 10
println(user.age)
user.age = 20
println(user.age)
Not Null
由于 Kotlin 不允许定义任何非空的非抽象属性,但是实际使用时可能也需要定义这样的属性,这时就需要 not null 方法来实现。
class NotNullFoo {
var bar: String by Delegates.notNull()
}
val foo = NotNullFoo()
foo.bar = "bar"
Map Val
Map Val 可以用于将所有属性保存在一个 Map 中,在使用 JSON 等数据格式或者实现某些动态特性时这种功能很有用。
class Account(val map: Map<String, Any?>) {
val name: String by Delegates.mapVal(map) {
o, p ->
println("$o -> $p")
"default name"
}
val age: Int by Delegates.mapVal(map) {
o, p ->
println("$o -> $p")
0
}
}
val account = Account(mapOf(
"name" to "John",
"age" to 25
))
println(account.name)
println(account.age)
mapVar()为以上的可变版本。