Kotlin 只读属性,带和不带 getter

Posted

技术标签:

【中文标题】Kotlin 只读属性,带和不带 getter【英文标题】:Kotlin read only property with and without getter 【发布时间】:2021-11-11 00:46:24 【问题描述】:

这些是等价的吗?

val foo = someFooReturningFunction()

val foo get() = someFooReturningFunction()

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

使用 get() someFooReturningFunction() 会在每次访问属性时进行评估,否则只会评估一次。

【问题讨论】:

【参考方案1】:

它们不等价。自定义 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,直接访问支持字段。然而,这是一个实现细节,不能依赖。

【讨论】:

【参考方案2】:

没有。除了@hotkey 的原因,这里有一个使用可变属性的简单演示,显示它们何时绝对不等价。 TLDR:如果您的属性是使用可变属性计算的,请始终在初始化程序上使用自定义 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!

【讨论】:

以上是关于Kotlin 只读属性,带和不带 getter的主要内容,如果未能解决你的问题,请参考以下文章

带和不带 () 的条件运算符

带和不带的 SQL 查询

在mysql中执行带和不带索引的查询

带和不带 lambda 的 pandas apply()

带和不带引号和括号的 setTimeout 之间的区别

在 Hive 中处理带和不带双引号的数据