Kotlin 委托
类委托
委托模式实现继承的一个很好的替代方式。委托模式使得我们可以用组合来替代继承,更进一步它还使我们可以模拟mixin 类(Flutter)
这是官网的一个委托例子
interface Base {
fun print()
fun printB()
}
class BaseImpl(val x: Int) : Base {
override fun print() { print(x) }
override fun printB() { println(x) }
}
class Derived(b: Base) : Base by b{
//可以只重写要覆覆盖的方法
override fun printB() { log(x) }
}
fun main() {
val b = BaseImpl(10)
Derived(b).print()
Derived(b).printB()
}
上面例子:Derived 的所有公有成员都委托 b 给来实现接口Base。 同时覆盖重写了printB 方法
在委托模式中,有2个对象参与同一个请求的处理,接受请求的对象将请求委托给另一个对象来处理。委托模式是一项技巧,其他的几种设计模式如:策略模式、状态模式和访问者模式都是委托模式的具体场景应用。
属性委托
2.1 延迟属性(lazy properties): 其值只在首次访问时计算
先看个例子
val lazyValue: String by lazy {
println("computed!")
"Hello"
}
fun main() {
println(lazyValue)
println(lazyValue)
}
//resut log
//computed!
//"Hello"
//"Hello"
顾名思义,lazy委托就是延迟加载,就是属性只有在第一次使用的时候初始化,得到值,并缓存值,后续使用这个属性不会重新初始化,而是直接使用缓存值
- lazy 接收一个 lambda 表达式,最后一行代表返回值。
- 默认情况下,对于 lazy 属性的求值是同步锁的(synchronized),是可以保证线程安全的,但是如果不需要线程安全和减少性能花销可以可以使用lazy(LazyThreadSafetyMode.NONE){}
2.2 可观察属性(observable properties): 监听器会收到有关此属性变更的通知
class User {
var name: String by Delegates.observable("<no name>") {
prop, old, new ->
println("$old -> $new")
}
}
fun main() {
val user = User()
user.name = "first"
user.name = "second"
}
可观察属性的含义是:可以通过Delegates.observable 回调来监听值的变更。这个是一个很好用的方法。可以用来实现响应式编程。
想想dataBinddingn的原理,通过Delegates.observable完全可以手工实现一个类似的数据驱动UI更改,而不需要引入任何框架。
- Delegates.vetoable() 跟 observable类似,提供了否决的功能,就是在属性被赋新值生效之前会调用
2.3 把多个属性储存在一个映射(map)中,而不是每个存在单独的字段中
class User(val map: Map<String, Any?>) {
val name: String by map
val age: Int by map
}
val user = User(mapOf(
"name" to "John Doe",
"age" to 25
))
println(user.name) // Prints "John Doe"
println(user.age) // Prints 25
一个常见的用例是在一个映射(map)里存储属性的值. 这个我理解其实是类似第二构造函数的功能,通常用在像解析 JSON等场景,跟前端的React,Vue的通过Prop传递值类似