Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

مراقبو الخصائص

جزء من قسم البرمجة كائنية التوجه في رحلة 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اختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس البرمجة كائنية التوجه

تدرّب بنفسك: Playground لـ Swift