Menu
Coddy logo textTech

צופי מאפיינים

חלק מהיחידה תכנות מונחה עצמים במסלול ה-Swift של Coddy. שיעור 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: הוסף didSet שמתקן ערכים מחוץ לטווח הזה, ומוסיף אזהרת low אל alerts בכל פעם שהרמה המתוקנת יורדת מתחת ל-20% מהקיבולת (והרמה הקודמת לא הייתה נמוכה).

הקוד שסופק קורא את הקיבולת ואז משנה אותה ב-+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 אונליין