【问题标题】:Getting the hang of Kotlin Delegates掌握 Kotlin 代表的窍门
【发布时间】:2020-06-25 16:32:42
【问题描述】:

我正在努力将我的头包裹在 Kotlin 代表身上。我发现将它与 generics 一起使用时特别棘手。就我而言,我想要一个可以存储任意类型值的委托。我第一次访问委托属性时,它会返回存储的值。所有后续访问只返回null。如果我再次设置该值,则下一次访问将返回该值,并且所有后续访问操作将再次返回null。它会像这样工作:

val a: Int by AccessOnce() // or String, or Boolean, or whatever
println(a) // null
a = 42
println(a) // 42
println(a) // null

a = 100
println(a) // 100
println(a) // null

这是我目前拥有的代码,但对 getValuesetValue 签名不满意。你能帮帮我吗?

import kotlin.reflect.KProperty

class AccessOnce <T> {
    var storedValue: T? = null
    operator fun getValue(thisRef: T?, property: KProperty<*>): T? {
        val retVal =  storedValue
        storedValue = null
        return retVal
    }

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

}

【问题讨论】:

  • 您可以实现ReadWriteProperty 接口以确保您的委托对象具有正确的签名。
  • 好的,很酷,但我对R - the type of object which owns the delegated property 感到困惑。这是什么意思?
  • ReadWriteProperty 是一个接口,所以在getValue 函数内部this 是(在你的情况下)AccessOnce 类。但是你在其他类中使用val a: Int by AccessOnce()R 必须是拥有a 的对象的类型(或超类型)。

标签: kotlin delegates delegation


【解决方案1】:

您的代码的问题是您将thisRef 的类型和属性本身的类型混为一谈。 thisRef 是具有被委托属性的任何对象。在大多数情况下,您只需将其设为Any 类型,这样您的委托就可以在您喜欢的任何类中使用。但是,如果您有一种仅适用于某种类型的类的特殊类型的委托,您可以将该类型用于 thisRef,然后在操作符函数中,您可以让您的 getter 和/或 setter 调用该类上的其他函数或做其他工作。

因此,要修复您的问题,您只需将 thisRef 更改为 Any

class AccessOnce <T> {
    var storedValue: T? = null
    operator fun getValue(thisRef: Any, property: KProperty<*>): T? {
        val retVal =  storedValue
        storedValue = null
        return retVal
    }

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

}

顺便说一句,getValue 可能是单行:

    operator fun getValue(thisRef: Any, property: KProperty<*>): T? =
         storedValue.also { storedValue = null }

【讨论】:

    猜你喜欢
    • 2018-04-25
    • 2013-06-19
    • 1970-01-01
    • 1970-01-01
    • 2011-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-03
    相关资源
    最近更新 更多