Menu
Coddy logo textTech

プロパティオブザーバー

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 -> 15

willSetは変更前に実行され、これから設定される値が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 20

didSetは値を有効な状態に保つのに適した場所です。独自の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]
challenge icon

チャレンジ

簡単

クラス Tank を完成させてください。保存プロパティ level は 0 以上 capacity 以下の範囲に収まる必要があります。その範囲外の値を修正し、修正後のレベルが capacity の 20% 未満になり、かつ以前のレベルが低い状態でなかった場合は、警告 low を alerts に追加する didSet を追加してください。

用意されたコードは容量を読み取り、その後 +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)")
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: Swiftプレイグラウンド