Kotlin只读有和没有吸气剂的财产

时间:2017-02-09 18:21:02

标签: kotlin

这些是等价的吗?

  • val foo = someFooReturningFunction()

  • val foo get() = someFooReturningFunction()

我理解它们的文档的方式,但在我自己的测试中,它们不是。

每次访问属性时都会使用 get() someFooReturningFunction()进行评估,而不会仅评估一次。

2 个答案:

答案 0 :(得分:7)

它们并不等同。确实对每个属性访问进行了自定义getter的评估,类似于普通函数,而没有自定义访问器的val属性仅在初始化时被评估一次(并且实际存储在JVM上的final字段中平台)。

以下是至少一些差异:

  • 如果属性具有自定义getter(或open,因此可能会被自定义getter覆盖),则控制流分析和可空性推理会将其考虑在内,因为没有保证该属性在后续调用中返回相同的值:

    if (someObject.defaultGetterProperty != null) {
        someObject.defaultGetterProperty.let { println(it) } // OK
    }
    

    if (someObject.propertyWithCustomGetter != null) {
        someObject.propertyWithCustomGetter { println(it) } // Error: cannot smart-cast
    }
    
  • 当属性为private时,如果它没有自定义getter,则根本不会生成getter,直接访问后备字段。然而,这是一个实现细节,而不是可依赖的东西。

答案 1 :(得分:1)

没有。除了@ hotkey的原因,这里还有一个简单的演示,使用可变属性显示它们肯定不相同的时候。 TLDR:如果您的属性是使用mutable属性计算的,请始终在初始化程序上使用自定义getter。

data class Calculation(val value1: Int, var value2: Int) {
    val sum: Int = value1 + value2
    val sumWithGetter: Int
        get() = value1 + value2
}

val calculation = Calculation(1, 2)
println(calculation.sumWithGetter) // prints 3
println(calculation.sum)           // prints 3

calculation.value2 = 0
println(calculation.sumWithGetter) // prints 1 (correct)
println(calculation.sum)           // prints 3!