我目前有一个声明如下的属性:
class Foo(val base : FooBase){
var _number: Int? = null
override var number: Int
get() = _number ?: base.number
set(value) {_number = value}
}
但是,我有很多这样的属性,导致相当多的代码重复。有办法避免这种情况吗?我理解属性委派是一种方法,但我不确定如何正确实现ReadWriteProperty<...>
。如果我应该使用它,我如何使用“属性”值?
答案 0 :(得分:6)
您需要创建一个扩展ReadWriteProperty
的类来提供功能(代码示例基于不安全的延迟实现)
class UninitializedProperty<T>(private val getter: () -> T) : ReadWriteProperty<Any?, T> {
var _value: Any? = UNINITIALIZED_VALUE
@Suppress("UNCHECKED_CAST")
override fun getValue(thisRef: Any?, property: KProperty<*>): T = if(_value === UNINITIALIZED_VALUE) getter() else _value as T
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
_value = value
}
private object UNINITIALIZED_VALUE
}
接下来,定义一个辅助方法,以保持与lazy
等标准委托的一致性:
fun <T> uninitialized(getter: () -> T): ReadWriteProperty<Any?, T> = UninitializedProperty(getter)
现在你可以使用它了:
class Foo(val base: FooBase) {
override var number: Int by uninitialized { base.number }
}
注意:该类不是线程安全的。
检查official documentation以获取有关委派的更多信息。
答案 1 :(得分:2)
这是对Yoav Sternberg的答案的表现改进。如你所见,它不那么通用,但它避免了自动装箱:
class IntUninitializedProperty(private val getter: () -> Int) {
private var isInitialised = false
private var value: Int = 0
fun getValue(thisRef: Any?, property: KProperty<*>): Int = if(isInitialised) value else getter()
fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) {
this.value = value
isInitialised = true
}
}