【问题标题】:Kotlin property delegation not working as expectedKotlin 财产委托未按预期工作
【发布时间】:2022-01-10 15:17:09
【问题描述】:

我对不同的行为感到困惑,具体取决于我使用的是 getter 还是委托属性。考虑以下几点:

class Test {
    class Parts(val a: String, val b: String)

    var raw = ""
    private var cachedParts: Parts? = null

    val parts: Parts
        get() {
            println("@2")
            return cachedParts
                ?: raw.split("/")
                    .let { Parts(it.getOrElse(0) { "" }, it.getOrElse(1) { "" }) }
                    .also { cachedParts = it }
        }

    // WITH GETTERS:
    val partA get() = parts.a
    val partB get() = parts.b
}

fun main() {
    val t = Test()
    println("@1")
    
    t.raw = "one/two"

    println("a=${t.partA}, b=${t.partB}")
}

此代码在第一次访问parts 时将字符串raw 分成两部分。以后对parts 的所有调用都将返回缓存的部分,即使raw 发生更改。输出:

@1
@2
@2
a=one, b=two

raw 的值在创建Test 时为空,但在我们将raw 设置为某个字符串之前不会调用访问器。当partApartB 最终被访问时,它们包含正确的值。

如果我改用属性委托,代码将不再有效:

class Test {
    class Parts(val a: String, val b: String)

    var raw = ""
    private var cachedParts: Parts? = null

    val parts: Parts
        get() {
            println("@2")
            return cachedParts
                ?: raw.split("/")
                    .let { Parts(it.getOrElse(0) { "" }, it.getOrElse(1) { "" }) }
                    .also { cachedParts = it }
        }

    // WITH DELEGATION:
    val partA by parts::a
    val partB by parts::b
}

fun main() {
    val t = Test()
    println("@1")
    
    t.raw = "one/two"

    println("a=${t.partA}, b=${t.partB}")
}

我在这里所做的只是将partA 委托给parts::apartB 也是如此。出于某种奇怪的原因,partApartB 现在在设置raw 的值之前被访问,所以cachedParts 用两个空部分初始化。输出:

@2
@2
@1
a=, b=

有人能解释一下这里发生了什么吗?

【问题讨论】:

    标签: kotlin properties getter delegation


    【解决方案1】:

    在文档here 中查看您的委托属性转换为什么。例如,partA 转换为:

    private val partADelegate = parts::a
    val partA: String
        get() = partADelegate.getValue(this, this::partA)
    

    请注意,可调用引用表达式part::a 用于初始化partADelegate。此表达式在创建 Test 的实例时计算,在 println("@1") 之前。

    要评估parts::a,必须首先评估parts。毕竟这是对partsa属性的引用,而不是对parts的引用。

    因此,parts 最终会在 raw 获得其值之前被评估。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-15
      • 2021-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多