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

التهيئة وsuper

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

عندما يضيف صنف فرعي خاصية مخزّنة بدون قيمة افتراضية، فإنه يحتاج إلى مُهيِّئ خاص به. يعيّن أولًا خصائصه الخاصة، ثم يستدعي مُهيِّئ الصنف الفائق باستخدام super.init(...):

class Animal {
    let name: String
    init(name: String) { self.name = name }
}

class Bird: Animal {
    let canFly: Bool

    init(name: String, canFly: Bool) {
        self.canFly = canFly
        super.init(name: name)
    }
}

let p = Bird(name: "Pip", canFly: false)
print("\(p.name) \(p.canFly)")

الناتج:

Pip false

الترتيب مهم: يجب أن تكون لخصائص الفئة الفرعية قيم قبل تشغيل super.init، ولا يمكن استخدام الخصائص الموروثة إلا بعد ذلك. يتحقق Swift من هذا وقت الترجمة:

init(name: String, canFly: Bool) {
    // print(self.name)      // خطأ: استخدام self قبل super.init
    self.canFly = canFly     // 1. الخصائص الخاصة
    super.init(name: name)   // 2. الصنف الأساسي
    print(self.name)         // 3. الآن يمكن استخدام كل شيء
}

بمجرد أن يعرّف الصنف الفرعي مُهيّئه الخاص، فإنه لا يعود يرث مُهيّئات الصنف الفائق. يمكن للصنف الفرعي أيضًا أن يتجاوز مُهيّئًا بالمعلمات نفسها، مع وضع علامة override init عليه:

class Timer {
    var seconds: Int
    init(seconds: Int) { self.seconds = seconds }
}

class SafeTimer: Timer {
    override init(seconds: Int) {
        super.init(seconds: max(0, seconds))
    }
}

print(SafeTimer(seconds: -5).seconds)
print(SafeTimer(seconds: 30).seconds)

الناتج:

0
30

يهيّئ كل مستوى من مستويات التسلسل الهرمي الجزء الخاص به، ويسلّم الباقي إلى صنفه الفائق، لذا تحصل كل خاصية في السلسلة على قيمة مرة واحدة بالضبط:

class Vehicle {
    let wheels: Int
    init(wheels: Int) { self.wheels = wheels }
}

class Car: Vehicle {
    let seats: Int
    init(seats: Int) {
        self.seats = seats
        super.init(wheels: 4)
    }
}

class Taxi: Car {
    let company: String
    init(company: String) {
        self.company = company
        super.init(seats: 5)
    }
}

let t = Taxi(company: "City Cabs")
print("\(t.company): \(t.wheels) wheels, \(t.seats) seats")

الناتج:

City Cabs: 4 wheels, 5 seats
challenge icon

التحدي

سهل

يخزّن Product كلًا من name وprice (بالسنتات). صرّح بالصنف الفرعي DiscountedProduct الذي يحتوي على percent مخزّنًا. يأخذ المُهيِّئ name وprice وpercent، ويخزّن percent، ويستدعي super.init بالسعر بعد تخفيضه بنسبة مئوية (مع التقريب إلى الأسفل). تُحتسب قيمة percent خارج النطاق 0-100 على أنها 0. أضف أسلوبًا label() في DiscountedProduct يعيد tea: 450 (10% off).

يقرأ الكود المزوَّد الأسطر بالصيغة name,price,percent، وينشئ كائنًا من DiscountedProduct لكل سطر، ثم يطبع label().

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

جرّب بنفسك

// كود الإدخال/الإخراج المُزوَّد: أبقِه كما هو
var input: [String] = []
while let line = readLine() { input.append(line) }
for line in input {
    let p = line.split(separator: ",").map { String($0) }
    let item = DiscountedProduct(name: p[0], price: Int(p[1])!, percent: Int(p[2])!)
    print(item.label())
}
quiz iconاختبر نفسك

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

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

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