You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin Getter/Setter引发无限递归:如何使volume外部赋值持久生效?

解决Kotlin中Animal类Volume字段的赋值与计算问题

要实现「默认由weight*height计算volume,外部赋值后保留该值不再重新计算」的需求,核心是用额外的 backing 变量区分「外部赋值」和「默认计算」两种状态,既避免赋值失效,也解决setter递归问题。

方案一:用可空类型的backing变量

class Animal(var weight: Double, var height: Double) {
    // 可空变量存储外部赋值的volume,null表示未被外部赋值
    private var _volume: Double? = null

    var volume: Double
        get() = _volume ?: weight * height // 有外部赋值就用赋值的,否则计算
        set(value) {
            _volume = value // 直接给backing变量赋值,避免递归
        }
}

方案二:用布尔标记+非空backing变量

如果不想用可空类型,也可以加布尔标记区分状态:

class Animal(var weight: Double, var height: Double) {
    private var _volume: Double = 0.0
    private var isVolumeSet = false // 标记是否被外部赋值过

    var volume: Double
        get() = if (isVolumeSet) _volume else weight * height
        set(value) {
            _volume = value
            isVolumeSet = true
        }
}

测试验证

运行以下代码就能看到效果:

fun main() {
    val dog = Animal(2.0, 3.0)
    println(dog.volume) // 输出6.0,默认计算值

    dog.volume = 20.0
    println(dog.volume) // 输出20.0,外部赋值生效

    dog.weight = 5.0 // 修改weight
    println(dog.volume) // 仍然输出20.0,不会重新计算,符合需求
}

原有代码问题解析

  • 若直接在getter里写return weight * height,每次获取volume都会重新计算,外部赋值的结果会被覆盖。
  • 若setter里不用backing变量/field,直接写volume = value,会无限递归调用setter方法,导致栈溢出——这是因为Kotlin属性setter本质是函数,直接赋值属性会再次触发setter。

内容的提问来源于stack exchange,提问作者user1906450

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 23:40:26