【发布时间】: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 设置为某个字符串之前不会调用访问器。当partA 和partB 最终被访问时,它们包含正确的值。
如果我改用属性委托,代码将不再有效:
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::a,partB 也是如此。出于某种奇怪的原因,partA 和partB 现在在设置raw 的值之前被访问,所以cachedParts 用两个空部分初始化。输出:
@2
@2
@1
a=, b=
有人能解释一下这里发生了什么吗?
【问题讨论】:
标签: kotlin properties getter delegation