了解 var 和 val 对属性的 getter 和 setter 的影响

时间:2021-04-29 19:44:07

标签: kotlin oop

假设我有一个 Kotlin 类 Dog,有两个属性 weightweightInKgs

class Dog(val weight: Double) {  
    // property without initializing works. Why?
    val weightinKgs: Double
    get() = weight/ 2.2;
}

上面的代码运行没有错误。我知道 Kotlin 中的每个属性都必须初始化,那么为什么在不初始化属性的情况下定义一个 getter 呢?其次,当 valvar 更改为 weightInKgs 时,会产生一个要求初始化的错误。将其更改为 var 会如何破坏代码?

class Dog(val weight: Double) {
    // well its doesn't work now. 
    var weightinKgs: Double
        get() = weight/ 2.2;
}

2 个答案:

答案 0 :(得分:2)

每个带有支持字段的属性都必须初始化。如果您定义了一个不使用支持字段的自定义 getter,并且不在声明站点使用 = 为支持字段分配值,那么它没有一个值,因此没有什么可初始化。

如果您将属性定义为 var 而不定义不使用支持字段的自定义 setter,那么它再次具有您必须初始化的支持字段(因为隐式 setter 使用了一个)。< /p>

答案 1 :(得分:0)

如果不是很明显,get() 是每次调用时都会计算一个值 (weight / 2.2) 的函数。基本上相当于这个

fun getWeightInKgs(): Double {
    return weight / 2.2
}

所以这就是它没有支持字段的原因,它实际上并不存储值。但是 Kotlin 将这些类型的 getX() 函数(以及 setis 等)呈现为属性,并鼓励您使用属性访问语法,因此 dog.weightInKgs 而不是 {{1 }}。有点隐藏了具体的实现细节

如果你不想每次都计算重量,只想做一次,那你就做

dog.getWeightInKgs()

然后它有一个支持字段,因为该值必须存储在某个地方。你也可以有一个 getter 函数来引用一个私有的 val weightInKgs = weight / 2.2 val 并返回它的值,而不是 giving the property itself a backing field,但是如果你需要做那种事情,你可能会明白你为什么会这样!这通常是因为当您的 getter 和/或 setter 正在做一些比隐藏或验证内部数据值更复杂的事情时