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

Swift子类中如何修改属性值?计算属性赋值异常咨询

解决Swift子类计算属性Setter看似生效但值未更新的问题

首先得敲黑板明确一个核心点:计算属性本身不存储值——它的get方法负责返回内容,set方法只是接收新值的入口,真正要让属性“看起来更新了”,必须在setter里修改关联的存储属性(比如父类的currentSpeed或者子类自己的gear)。如果你的setter只是空转或者没碰存储属性,那自然调用set后,属性的实际表现(也就是get返回的结果)不会有变化。

我们先把你的代码补全,模拟出你遇到的问题场景:

class Vehicle {
    var currentSpeed = 1.0
    var description: String {
        return "The current speed is \(currentSpeed) miles per hour"
    }
    func makeNoise() { }
}

class Car: Vehicle {
    var gear = 0
    override var description: String {
        get {
            return super.description + " in gear \(gear)"
        }
        set {
            // 错误示例:只做了打印但没修改任何存储属性
            print("收到新的描述:\(newValue)")
        }
    }
}

// 测试代码
let myCar = Car()
print(myCar.description) // 输出:The current speed is 1.0 miles per hour in gear 0
myCar.description = "The current speed is 50.0 miles per hour in gear 3"
print(myCar.description) // 输出还是原来的内容,因为setter没动存储属性

问题根源

你在setter里没有更新currentSpeed或gear这些实际保存数据的存储属性,计算属性的get方法依然依赖这些老的存储值返回结果,所以即使调用了set,最终呈现的内容还是和之前一样。

正确的实现方式

在setter里解析传入的newValue,把里面的有效信息提取出来更新对应的存储属性,这样get方法就能返回新的结果了:

class Car: Vehicle {
    var gear = 0
    override var description: String {
        get {
            return super.description + " in gear \(gear)"
        }
        set {
            // 从newValue里提取速度和档位信息
            let speedRegex = try! NSRegularExpression(pattern: "The current speed is ([0-9.]+)")
            if let speedMatch = speedRegex.firstMatch(in: newValue, range: NSRange(newValue.startIndex..., in: newValue)),
               let speedRange = Range(speedMatch.range(at: 1), in: newValue),
               let speed = Double(newValue[speedRange]) {
                currentSpeed = speed
            }
            
            let gearRegex = try! NSRegularExpression(pattern: "in gear ([0-9]+)")
            if let gearMatch = gearRegex.firstMatch(in: newValue, range: NSRange(newValue.startIndex..., in: newValue)),
               let gearRange = Range(gearMatch.range(at: 1), in: newValue),
               let gearNum = Int(newValue[gearRange]) {
                gear = gearNum
            }
        }
    }
}

// 测试代码
let myCar = Car()
print(myCar.description) // The current speed is 1.0 miles per hour in gear 0
myCar.description = "The current speed is 50.0 miles per hour in gear 3"
print(myCar.description) // The current speed is 50.0 miles per hour in gear 3

关键要点总结

  • 计算属性只是“逻辑层”,它的读写行为完全依赖背后的存储属性
  • 重写父类计算属性时,要确保setter逻辑和父类的存储属性(比如currentSpeed)正确交互
  • 别把计算属性当成存储属性用——它本身不保存任何值,只是负责把输入转成存储属性的变化,或者把存储属性的值转成输出

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:24:28