属性观察器
本课属于 Coddy Swift 学习旅程的“面向对象编程”单元。第 13 课,共 57 课。
属性观察器会在存储属性发生变化时运行代码。didSet会在新值存储后立即运行,在其中,oldValue保存的是之前的值:
class Player {
var score = 0 {
didSet {
print("score \(oldValue) -> \(score)")
}
}
}
let p = Player()
p.score = 10
p.score += 5输出:
score 0 -> 10
score 10 -> 15willSet 会在更改前运行,并将即将设置的值作为 newValue。属性获得初始值时,不会运行观察器:
struct Thermostat {
var target = 20 {
willSet { print("changing to \(newValue)") }
didSet { print("changed from \(oldValue)") }
}
}
var t = Thermostat()
t.target = 22输出:
changing to 22
changed from 20didSet 是保持值有效的好地方。在属性自己的 didSet 中赋值,不会再次触发观察器:
struct Volume {
var level = 5 {
didSet {
if level > 10 { level = 10 }
if level < 0 { level = 0 }
}
}
}
var v = Volume()
v.level = 42
print(v.level)
v.level = -3
print(v.level)输出:
10
0观察器还可以记录历史记录或更新相关状态,这样逻辑就会放在属性旁边,而不是散落在代码各处:
class Account {
var history: [Int] = []
var balance = 0 {
didSet { history.append(balance - oldValue) }
}
}
let a = Account()
a.balance = 100
a.balance = 70
print(a.history)输出:
[100, -30]挑战
简单补全类 Tank。它的存储属性 level 必须保持在 0 和 capacity 之间:添加一个 didSet,用于修正超出此范围的值;如果修正后的等级低于容量的 20%,且之前的等级不低,则将警告 low 添加到 alerts 中。
提供的代码会读取容量,然后根据 +n 或 -n 更改等级。每次更改后,它都会输出等级,最后输出 alerts: 和警告数量。
你的代码要写在 Tank.swift 中。main.swift 中包含提供的输入输出代码,不能编辑。
亲手试试
// 提供的输入/输出代码:保持原样
var input: [String] = []
while let line = readLine() { input.append(line) }
let tank = Tank(capacity: Int(input[0])!)
for cmd in input.dropFirst() {
let n = Int(cmd.dropFirst())!
tank.level += cmd.hasPrefix("+") ? n : -n
print(tank.level)
}
print("alerts: \(tank.alerts.count)")
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Swift 在线编辑器