【问题标题】:Kotlin val difference getter override vs assignmentKotlin val 差异 getter 覆盖与分配
【发布时间】:2018-01-08 01:43:29
【问题描述】:

我开始使用 Kotlin 玩 arround,并阅读了一些关于使用自定义 getter 的 mutable val 的内容。如 hereKotlin Coding Convention 中所述,如果结果可以更改,则不应覆盖 getter。

class SampleArray(val size: Int) {
    val isEmpty get() = size == 0  // size is set at the beginning and does not change so this is ok
}

class SampleArray(var size: Int) {
    fun isEmpty() { return size == 0 }  // size is set at the beginning but can also change over time so function is prefered
}

但仅从使用指南的角度来看,以下两者之间的区别在哪里

class SampleArray(val size: Int) {
    val isEmpty get() = size == 0  // size can not change so this can be used instad of function
    val isEmpty = size == 0        // isEmpty is assigned at the beginning ad will keep this value also if size could change
}

this 的答案我可以看到,对于 getter 覆盖,值没有被存储。还有其他什么地方 getter 覆盖与分配不同吗?也许与代表或拉丁?

【问题讨论】:

    标签: kotlin getter


    【解决方案1】:

    这里的关键区别在于,在val isEmpty get() = ... 中,每次访问属性时都会评估主体,而在val isEmpty = ... 中,右侧的表达式在对象构造期间被评估,结果存储在@987654321 @ 并且每次使用该属性时都会返回这个确切的结果。

    因此,第一种方法适用于您希望每次都计算结果的情况,而第二种方法适用于您希望只计算一次并存储结果的情况。

    【讨论】:

    • 什么是支持字段?您的链接没有解释它。
    • 这是一个存储属性值的字段。它可以是可变的或不可变的(在 JVM 术语中为final)。
    【解决方案2】:

    在您的第二个示例中,size 是不可变值,因此两种方式都有效。

    但是,具有覆盖 getter get() = size == 0 has no backing field 的变体,因此每次访问 isEmpty 变量时都会评估 size == 0

    另一方面,当使用初始化器 = size == 0 时,表达式 size == 0 在构造过程中被求值(检查确切的时间和方式 - An in-depth look at Kotlin’s initializers)并存储到 backing field,然后返回其中的值你访问变量。

    【讨论】:

    • 如果getter函数示例被声明为var会有什么区别?
    • 根据文档,在上面的示例中没有效果。当使用val 时,setter 是不允许,当使用var 时,你可以(可选地)实现setter - 如果你不这样做,那么默认的@987654334将使用 @ 标识符 (Backing fields)。但是因为你实现了自定义getter,所以这个field没有用(除非你在getter中使用)。
    • 什么是支持字段? kotlin 文档没有解释它。
    猜你喜欢
    • 2016-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-27
    • 1970-01-01
    • 2021-04-16
    • 1970-01-01
    相关资源
    最近更新 更多