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
相关产品推荐
相关产品推荐

