我想创建一个非空的特定类型的变量,例如Foo.
然后我希望对变量的所有访问都返回Foo,就像一个惰性委托一样,但是,我也希望能够重置它.
就像是:
var foo : String by Foo(init: {"bar"})
print(foo) // prints "bar"
foo = null // or foo.reset()
print(foo) // prints "bar"
Run Code Online (Sandbox Code Playgroud)
我试图解决的问题:我有一个适配器的索引,我需要在适配器内容更改时重新创建.所以在改变时我想清除索引,下次有人试图访问它时,我想重新创建它.
如果目标是进行延迟初始化var property,可以将其重置为初始状态,则可以调整Kotlin的SynchronizedLazyImpl以允许无效功能:
private object UNINITIALIZED_VALUE
class InvalidatableLazyImpl<T>(private val initializer: () -> T, lock: Any? = null) : Lazy<T>, Serializable {
@Volatile private var _value: Any? = UNINITIALIZED_VALUE
private val lock = lock ?: this
fun invalidate(){
_value = UNINITIALIZED_VALUE
}
override val value: T
get() {
val _v1 = _value
if (_v1 !== UNINITIALIZED_VALUE) {
return _v1 as T
}
return synchronized(lock) {
val _v2 = _value
if (_v2 !== UNINITIALIZED_VALUE) {
_v2 as T
}
else {
val typedValue = initializer()
_value = typedValue
typedValue
}
}
}
override fun isInitialized(): Boolean = _value !== UNINITIALIZED_VALUE
override fun toString(): String = if (isInitialized()) value.toString() else "Lazy value not initialized yet."
operator fun setValue(any: Any, property: KProperty<*>, t: T) {
_value = t
}
}
Run Code Online (Sandbox Code Playgroud)
然后可以使用如下:
private val fooDelegate = InvalidatableLazyImpl({"bar"})
var foo:String by fooDelegate
println(foo); // -> "bar"
foo = "updated"
println(foo); // -> "updated"
fooDelegate.invalidate()
println(foo); // -> "bar"
Run Code Online (Sandbox Code Playgroud)
显然,可以修改委托实现以允许null值作为重置,但是它可能使代码更难以推理,即:
println(obj.foo); //-> prints "bar
obj.foo = null //reset the value, implicitely
println(obj.foo); //-> prints "bar", but hey didn't I just said `null`
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2210 次 |
| 最近记录: |