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

المهيئات القابلة للفشل

جزء من قسم البرمجة كائنية التوجه في رحلة Swift على Coddy. الدرس 20 من 57.

لا يمكن إنشاء بعض القيم من كل إدخال. المُهيّئ القابل للفشل، المكتوب بصيغة init?، يُرجع nil بدلًا من نسخة عند كون الإدخال غير صالح، لذلك لا يمكن أن توجد نسخة غير صالحة أبدًا:

struct Percentage {
    let value: Int

    init?(_ value: Int) {
        guard value >= 0, value <= 100 else { return nil }
        self.value = value
    }
}

print(Percentage(42)?.value ?? -1)
print(Percentage(150)?.value ?? -1)

الناتج:

42
-1

نتيجة المُهيئ القابل للفشل هي قيمة اختيارية، لذا يجب على المستدعي فك تغليفها، عادةً باستخدام if let أو guard let:

struct Email {
    let address: String

    init?(_ text: String) {
        let parts = text.split(separator: "@")
        guard parts.count == 2, parts[1].contains(".") else { return nil }
        address = text.lowercased()
    }
}

for text in ["Ada@Mail.com", "not-an-email"] {
    if let email = Email(text) {
        print("valid: \(email.address)")
    } else {
        print("invalid: \(text)")
    }
}

المخرجات:

valid: ada@mail.com
invalid: not-an-email

تستخدم أنواع Swift الخاصة بها الفكرة نفسها: ‏Int("42") وDouble("x") هما مُهيِّئان قابلان للفشل، وكذلك مُهيِّئ التعداد init(rawValue:). ويمكن لمُهيِّئ قابل للفشل استدعاء هذه المُهيِّئات وتمرير الفشل:

struct Coordinate {
    let lat: Double
    let lon: Double

    init?(text: String) {
        let parts = text.split(separator: ",")
        guard parts.count == 2,
              let lat = Double(parts[0]), let lon = Double(parts[1]),
              abs(lat) <= 90, abs(lon) <= 180 else { return nil }
        self.lat = lat
        self.lon = lon
    }
}

print(Coordinate(text: "51.5,-0.1") != nil)
print(Coordinate(text: "95,10") != nil)

الناتج:

true
false

استخدم init? عندما تكون القيمة المفقودة معلومات كافية. استخدم مُهيئًا يُطلق خطأً، init(...) throws، عندما ينبغي للمتصل معرفة القاعدة التي فشلت:

struct Username {
    let text: String
    init(_ text: String) throws {
        guard text.count >= 3 else { throw NameError.tooShort }
        guard text.allSatisfy({ $0.isLetter }) else { throw NameError.badCharacters }
        self.text = text
    }
}
challenge icon

التحدي

سهل

أكمل البنية Rgb، التي تخزّن لونًا على هيئة red وgreen وblue من 0 إلى 255. يقرأ المهيئ القابل للفشل init?(hex:) نصًا مثل #FF8000: ويُرجع nil ما لم يكن النص هو # متبوعًا بستة أرقام سداسية عشرية بالضبط. استخدم Int(text, radix: 16) لكل زوج. أضف label محسوبة تُرجع rgb(255, 128, 0).

يقرأ الكود المزوّد لونًا واحدًا في كل سطر ويطبع التسمية أو invalid: text.

ضع كودك في Rgb.swift. يحتوي main.swift على كود الإدخال/الإخراج المزوّد، ولا يمكن تعديله.

جرّب بنفسك

// كود الإدخال/الإخراج المُزوَّد: أبقِه كما هو
var input: [String] = []
while let line = readLine() { input.append(line) }
for line in input {
    if let color = Rgb(hex: line) {
        print(color.label)
    } else {
        print("invalid: \(line)")
    }
}
quiz iconاختبر نفسك

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

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

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