如何使用kotlin委托属性的不同类型



我尝试写一个LiveData类,将原始(可空)值包装成Result类,清楚地指示是否存在值(Result)。成功)或不(结果。失败(.在整个应用程序中,我使用这个类来区分加载某些文件的过程是否成功。因此,出于这个原因,我决定在我的LiveData子类中也使用它,尽管命名并不像它可能的那样合理。为了简化工作,我们提供了一些流畅的辅助方法来执行不同情况下的代码。

sealed class Result<out T: Any> {
data class Success<out T: Any>(val value: T): Result<T>()
object Failure: Result<Nothing>()
fun onSuccess(block: (T) -> Unit): Result<T> {
if(this is Success) {
block(value)
}
return this
}
fun onFailure(block: () -> Unit): Result<T> {
if(this is Failure) {
block()
}
return this
}
fun handle(onSuccess: (T) -> Unit, onFailure: () -> Unit): Result<T> {
if(this is Success) {
onSuccess(value)
} else {
onFailure()
}
return this
}
}

所以我需要设置类型为T的值,但获得包装结果对象的能力。简单的方法是使用像setValue(value: T)这样的函数来更改值,并且使用getValue(): Result安全地接收值。但是我想使用kotlin的委托属性(safemutableelivedatadelegation)


abstract class SafeLiveData<T: Any> {
abstract val value: Result<T>
}
class SafeMutableLiveData<T: Any>: SafeLiveData<T>() {
private val mutableValue = MutableLiveData<T>()
override var value by SafeMutableLiveDataDelegation(mutableValue)
operator fun getValue(thisRef: Any?, property: KProperty<*>): SafeMutableLiveData<T> {
return this
}
fun ifAvailable(block: (T) -> Unit): SafeMutableLiveData<T> {
value.onSuccess(block)
return this
}
fun ifNotAvailable(block: () -> Unit): SafeMutableLiveData<T> {
value.onFailure(block)
return this
}
fun handle(ifAvailable: (T) -> Unit, ifNotAvailable: () -> Unit): SafeMutableLiveData<T> {
value.handle(ifAvailable, ifNotAvailable)
return this
}
}

只使用只读访问(覆盖val值…)一切都很好,但如何创建一个可以这样做的委托类?像这样:

private class SafeMutableLiveDataDelegation<T: Any>(private val mutableLiveData: MutableLiveData<T>) {
operator fun getValue(thisRef: Any?, property: KProperty<*>): Result<T> {
return  if(mutableLiveData.value != null)
Result.Success(mutableLiveData.value!!)
else
Result.Failure
}

operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
mutableLiveData.value = value
}
}

你不能。要求包括:

getValue()必须返回与属性(或其子类型)相同的类型。

value[setValue的参数]必须与属性(或其超类型)具有相同的类型。

并且没有类型P可以用于属性:Result<T>PP的子类型;且TPP的超类型。

但是你可以添加一个方法来获取T而不是将其设置为setter:

// inside SafeMutableLiveData
fun set(value: T) {
mutableLiveData.value = Result.Success(value)
}

最新更新