Menu
CoddyTech

Quan sát thuộc tính

Thuộc phần Lập trình hướng đối tượng trong hành trình Swift của Coddy. Bài học 13 trên 57.

Bộ quan sát thuộc tính chạy code mỗi khi thuộc tính được lưu trữ thay đổi. didSet chạy ngay sau khi giá trị mới được lưu, và bên trong đó, oldValue giữ giá trị trước đó:

class Player {
    var score = 0 {
        didSet {
            print("score \(oldValue) -> \(score)")
        }
    }
}

let p = Player()
p.score = 10
p.score += 5

Đầu ra:

score 0 -> 10
score 10 -> 15

willSet chạy trước khi giá trị thay đổi, với giá trị mới được truyền vào dưới dạng newValue. Các trình quan sát không chạy khi thuộc tính nhận giá trị ban đầu:

struct Thermostat {
    var target = 20 {
        willSet { print("changing to \(newValue)") }
        didSet { print("changed from \(oldValue)") }
    }
}

var t = Thermostat()
t.target = 22

Đầu ra:

changing to 22
changed from 20

didSet là nơi phù hợp để giữ cho một giá trị luôn hợp lệ. Gán giá trị cho thuộc tính bên trong chính didSet của thuộc tính đó sẽ không kích hoạt lại trình quan sát:

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)

Đầu ra:

10
0

Observer cũng có thể lưu lịch sử hoặc cập nhật trạng thái liên quan, nhờ đó logic nằm cạnh thuộc tính thay vì rải rác trong code:

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)

Đầu ra:

[100, -30]
challenge icon

Thử thách

Dễ

Hoàn thiện lớp Tank. Thuộc tính được lưu trữ level phải luôn nằm trong khoảng từ 0 đến capacity: thêm didSet để điều chỉnh các giá trị nằm ngoài khoảng đó và thêm cảnh báo low vào alerts bất cứ khi nào mức đã điều chỉnh xuống dưới 20% sức chứa (và mức trước đó không thấp).

Code được cung cấp đọc sức chứa, sau đó thay đổi +n hoặc -n. Code in ra mức sau mỗi lần thay đổi và cuối cùng in alerts: cùng số cảnh báo.

Code của bạn nằm trong Tank.swift. main.swift chứa code đầu vào/đầu ra được cung cấp và bạn không thể chỉnh sửa tệp này.

Tự làm thử

// Đoạn code đầu vào/đầu ra đã được cung cấp: giữ nguyên
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)")
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Playground Swift