我强加了可转让财产委托
internal object UNINITIALIZED_VALUE
class SynchronizedReassignableImpl<out T>(private val initializer: () -> T,
private val expiredPredicate: (T) -> Boolean,
lock: Any? = null) : Reassignable<T> {
@Volatile
private var _value: Any? = UNINITIALIZED_VALUE
private val lock = lock ?: this
override val value: T
get() {
if (!isExpired()) {
@Suppress("UNCHECKED_CAST") (_value as T)
}
return synchronized(lock) {
val _v2 = _value
@Suppress("UNCHECKED_CAST")
if (_v2 !== UNINITIALIZED_VALUE && !expiredPredicate.invoke(_value as T)) {
_v2 as T
} else {
val typedValue = initializer()
_value = typedValue
typedValue
}
}
}
@Suppress("UNCHECKED_CAST")
override fun isExpired(): Boolean = !isInitialized() || expiredPredicate.invoke(_value as T)
override fun isInitialized(): Boolean = _value !== UNINITIALIZED_VALUE
override fun toString(): String = if (isInitialized()) value.toString() else "Reassignable value not initialized yet."
operator fun getValue(any: Any, property: KProperty<*>): T = value
operator fun getValue(any: Nothing?, property: KProperty<*>): T = value
}
fun <T> reassignable(initializer: () -> T, expiredPredicate: (T) -> Boolean, lock: Any? = null): SynchronizedReassignableImpl<T> {
return SynchronizedReassignableImpl(initializer, expiredPredicate, lock)
}
interface Reassignable<out T> {
val value: T
fun isInitialized(): Boolean
fun isExpired(): Boolean
}
此代码声明Delegate Property的工作方式类似于惰性,但是在每次getter调用时,将调用谓词以定义值的状态(是否过期)。如果该值过期,则将重新分配该值。
例如,它正在工作
class SynchronizedReassignableImplTests {
@Test
fun isReassignable() {
val initializer = { mutableListOf<String>() }
val expiredPredicate = { l: List<String> -> l.size == 2 }
val list by reassignable(initializer, expiredPredicate)
Assertions.assertEquals(0, list.size)
list.add("item ${list.size}")
Assertions.assertEquals(1, list.size)
list.add("item ${list.size}") // list size is 2 on next getter's call it will be reassigned
Assertions.assertEquals(0, list.size)
list.add("item ${list.size}")
Assertions.assertEquals(1, list.size)
}
}
但是我只和Kotlin在一起工作了两天,并认为我的解决方案不是那么漂亮。 有人可以给我建议吗?还是Kotlin有本地解决方案?