如何为 kotlin 委托属性使用不同的类型
Posted
技术标签:
【中文标题】如何为 kotlin 委托属性使用不同的类型【英文标题】:How to use different types for kotlin delegation properties 【发布时间】:2021-10-18 12:18:19 【问题描述】:我尝试编写一个 LiveData 类,它将原始(可为空的)值包装到一个 Result 类中,清楚地表明是否有一个值( Result.Success )或不是(Result.Failure)。 在整个应用程序中,我使用这个类来区分加载某些文件的过程是否成功。因此,出于这个原因,我决定在我的 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 的委托属性 ( SafeMutableLiveDataDelegation ) 来做到这一点。
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
只使用只读访问(override val value by...)一切都很好,但是如何创建一个可以这样做的委托类呢?类似的东西:
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
【问题讨论】:
【参考方案1】:嗯,你不能。 requirements 包括:
getValue()
必须返回与属性(或其子类型)相同的类型。
value
[setValue
的参数] 必须与属性(或其超类型)属于同一类型。
并且没有类型 P
可以用于属性,这样:Result<T>
是 P
或 P
的子类型;而T
是P
或P
的超类型。
但是您可以只添加一个采用 T
的方法,而不是使其成为 setter:
// inside SafeMutableLiveData
fun set(value: T)
mutableLiveData.value = Result.Success(value)
【讨论】:
以上是关于如何为 kotlin 委托属性使用不同的类型的主要内容,如果未能解决你的问题,请参考以下文章