目录
- 类委托
- 属性委托
2.1. 方法一:可以按需继承ReadOnlyProperty、ReadWriteProperty
两个接口中的一个;
2.2. 方法二:自己定义,但方法参数必须和 1 中接口的方法参数一致; - 标准委托
3.1. 延迟属性 Lazy
3.2. 可观察属性 Observable
3.3. 把属性储存在映射中 - 使用场景
类委托(代理模式)
两种类代理的方法
interface Base {
fun print()
}
class BaseImpl(val x: Int) : Base {
override fun print() { print(x) }
}
// 第一种:这里直接使用关键字 by 进行代理
class Derived(base: Base) : Base by base
// 第二种:
class Derived(base: Base) : Base {
val base : Base
init {
this.base = base
}
override fun print() {
base.print() // base是BaseImpl的实例对象
}
}
// 测试
class Main {
fun main() {
val b = BaseImpl(10)
Derived(b).print() // prints 10
}
}
属性委托
语法结构: val/var <property name>: <Type> by <expression>
两种实现方法:
方法一:可以按需继承
ReadOnlyProperty、ReadWriteProperty
两个接口中的一个;// 读取属性 public interface ReadOnlyProperty<in R, out T> { public operator fun getValue(thisRef: R, property: KProperty<*>): T } // 读写属性 public interface ReadWriteProperty<in R, T> { // 关键字 operator 重载操作符 public operator fun getValue(thisRef: R, property: KProperty<*>): T public operator fun setValue(thisRef: R, property: KProperty<*>, value: T) }
示例代码:
class Delegate<T> : ReadWriteProperty<Any?, T> { // 重写了getValue()方法 override fun getValue(thisRef: Any?, property: KProperty<*>): T { return ... } override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) { } } class Main { var p: String by Delegate<String>() fun test() { val main = Main() print(main.p) // 会调用到Delegate中的getValue()方法 main.p = "Elson" // 会调用到Delegate中的setValue()方法 } }
方法二:自己定义,但方法参数必须和 1 中接口的方法参数一致;
class Delegate<T> { // 使用关键字 operator 来实现重载 operator fun getValue(thisRef: Any?, property: KProperty<*>): T { return "$thisRef, thank you for delegating '${property.name}' to me!" } operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) { println("$value has been assigned to '${property.name}' in $thisRef.") } }
示例代码:
class Main { var p: String by Delegate<String>() //属性 p 被代理 fun test() { val main = Main() print(main.p) // 会调用到Delegate中的getValue()方法 main.p = "Elson" // 会调用到Delegate中的setValue()方法 } }
标准委托
1. 延迟属性 Lazy
示例代码:
val lazyValue: String by lazy { println("computed!") "Hello" } fun main(args: Array<String>) { println(lazyValue) //第一次调用lazyValue时,会先初始化lazy{}作用区间的代码,即打印一个"computed!",然后返回一个"Hello"字符串并赋值给lazyValue; println(lazyValue) //第二次调用lazyValue时,直接将"Hello"赋值给lazyValue;可参考下面的源码 }
源码:
Lazy.kt
文件public fun <T> lazy(initializer: () -> T): Lazy<T> = SynchronizedLazyImpl(initializer) private object UNINITIALIZED_VALUE @JvmVersion private class SynchronizedLazyImpl<out T>(initializer: () -> T, lock: Any? = null) : Lazy<T>, Serializable { private var initializer: (() -> T)? = initializer @Volatile private var _value: Any? = UNINITIALIZED_VALUE // final field is required to enable safe publication of constructed instance private val lock = lock ?: this override val value: T get() { val _v1 = _value if (_v1 !== UNINITIALIZED_VALUE) { @Suppress("UNCHECKED_CAST") return _v1 as T //第二次执行操作时,这里直接返回对象 } return synchronized(lock) { val _v2 = _value if (_v2 !== UNINITIALIZED_VALUE) { @Suppress("UNCHECKED_CAST") (_v2 as T) } else { val typedValue = initializer!!()//第一次使用时执行这里,将lazy大括号内的代码进行初始化,并返回最后一行的数据并赋值给typedValue _value = typedValue initializer = null typedValue } } } override fun isInitialized(): Boolean = _value !== UNINITIALIZED_VALUE override fun toString(): String = if (isInitialized()) value.toString() else "Lazy value not initialized yet." private fun writeReplace(): Any = InitializedLazyImpl(value) }
2. 可观察属性 Observable
示例代码:
class User {
// 方法一:
var name: String by Delegates.observable("<no name>") {
prop, old, new ->
println("$old -> $new")
}
// 方法二:Delegates.observable()实际上就是对ObservableProperty的一层封装
var name : String by object : ObservableProperty<String>("<no name>") {
override fun afterChange(property: KProperty<*>, oldValue: String, newValue: String) {
println("$oldValue -> $newValue")
}
}
}
fun main() {
val user = User()
user.name = "first"
user.name = "second"
}
输出结果
< no name > -> first
first -> second
源码:
public inline fun <T> observable(initialValue: T, crossinline onChange: (property: KProperty<*>, oldValue: T, newValue: T) -> Unit):
ReadWriteProperty<Any?, T> = object : ObservableProperty<T>(initialValue) {
override fun afterChange(property: KProperty<*>, oldValue: T, newValue: T) = onChange(property, oldValue, newValue)
}
public inline fun <T> vetoable(initialValue: T, crossinline onChange: (property: KProperty<*>, oldValue: T, newValue: T) -> Boolean):
ReadWriteProperty<Any?, T> = object : ObservableProperty<T>(initialValue) {
// 需要返回一个boolean值,判断是否需要发射,默认为true
override fun beforeChange(property: KProperty<*>, oldValue: T, newValue: T): Boolean = onChange(property, oldValue, newValue)
}
public abstract class ObservableProperty<T>(initialValue: T) : ReadWriteProperty<Any?, T> {
private var value = initialValue
protected open fun beforeChange(property: KProperty<*>, oldValue: T, newValue: T): Boolean = true
protected open fun afterChange (property: KProperty<*>, oldValue: T, newValue: T): Unit {}
// 代理后,自动被调用
public override fun getValue(thisRef: Any?, property: KProperty<*>): T {
return value
}
// 代理后,自动被调用
public override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
val oldValue = this.value
// 判断是否需要发射,默认为true
if (!beforeChange(property, oldValue, value)) {
return
}
this.value = value
afterChange(property, oldValue, value)
}
}
3. 把属性储存在映射中
这部分不知道怎么看源码
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
))