final والتسلسلات الهرمية
جزء من قسم البرمجة كائنية التوجه في رحلة Swift على Coddy. الدرس 25 من 57.
تمنع final إجراء المزيد من التجاوز. لا يمكن تجاوز final func في أي فئة فرعية، ولا يمكن إنشاء فئات فرعية من final class على الإطلاق:
class Account {
final func id() -> String { "ACC" } // لا يمكن تجاوزه
}
final class Receipt { } // لا يمكن إنشاء فئات فرعية منه
// class GiftReceipt: Receipt { } // خطأ: الوراثة من فئة نهائيةضع علامة final على الطريقة عندما يجب ألّا تتمكن الفئات الفرعية من تغييرها، مثل طريقة تفرض قاعدة. ولا يزال بإمكانك تجاوز الطرق الأخرى لتخصيص التفاصيل:
class Checkout {
final func total(_ prices: [Int]) -> Int {
let sum = prices.reduce(0, +)
return sum - discount(sum)
}
func discount(_ sum: Int) -> Int { 0 }
}
class SaleCheckout: Checkout {
override func discount(_ sum: Int) -> Int { sum / 10 }
}
print(Checkout().total([50, 50]))
print(SaleCheckout().total([50, 50]))الناتج:
100
90يمكن أن تحتوي التسلسلات الهرمية على عدة مستويات. يتم البحث عن الطريقة بدءًا من فئة الكائن نفسه إلى الأعلى، ويتم تشغيل أول تطبيق يتم العثور عليه:
class Animal {
func move() -> String { "moves" }
func eat() -> String { "eats" }
}
class Bird: Animal {
override func move() -> String { "flies" }
}
class Penguin: Bird {
override func move() -> String { "swims" }
}
let p = Penguin()
print(p.move())
print(p.eat())الناتج:
swims
eatsاجعل التسلسلات الهرمية سطحية. يصعب تتبّع السلاسل العميقة، لأن سلوك كائن واحد يكون موزعًا على العديد من الأصناف. عندما تشترك الأنواع في السلوك من دون وجود علاقة is-a، تكون البروتوكولات (في الفصل التالي) عادةً الأداة الأفضل.
// عميق وهش
class A { }
class B: A { }
class C: B { }
class D: C { } // ماذا يرث D، ومن أين؟التحدي
سهليحتوي Discount على أسلوب final باسم apply(to:) يُرجع السعر مطروحًا منه amount(for:)، ولكن لا يُرجع قيمة أقل من 0، بينما يُرجع amount(for:) القيمة 0. صرّح عن PercentOff (يخزّن percent، والمقدار = السعر مضروبًا في النسبة المئوية / 100) وFixedOff (يخزّن value، والمقدار = القيمة)، على أن يحتوي كل منهما على مُهيّئ وتجاوز لـ amount(for:). يبقى apply(to:) نفسه في Discount.
يقرأ الكود المُ supplied السعر، ثم يطبّق الخصم p,10 أو f,300، ويطبّق كل خصم على السعر ويطبع 1000 -> 900.
ضع كودك في Discount.swift وPercentOff.swift وFixedOff.swift. يحتوي main.swift على كود الإدخال/الإخراج المُ supplied ولا يمكن تعديله.
جرّب بنفسك
// كود الإدخال/الإخراج المُزوَّد: أبقِه كما هو
var input: [String] = []
while let line = readLine() { input.append(line) }
let price = Int(input[0])!
for line in input.dropFirst() {
let p = line.split(separator: ",").map(String.init)
let d: Discount = p[0] == "p" ? PercentOff(percent: Int(p[1])!) : FixedOff(value: Int(p[1])!)
print("\(price) -> \(d.apply(to: price))")
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1الأصناف والكائنات
العمل مع الملفاتتعريف الأصنافالأساليب وselfالمُهيِّئاتالأصناف هي مراجعمراجعة - بطاقة المكتبة4التغليف
التحكم في الوصولللقراءة فقط من الخارجحماية الحالةالمهيئات القابلة للفشلمراجعة - الحساب البنكي7تعدد الأشكال والأنواع العامة
تعدد الأشكالتحويل الأنواعالدوال العامةالأنواع العامةمراجعة - حاسبة الأشكال5الوراثة
الفئات الفرعيةتجاوز الأساليبالتهيئة وsuperfinal والتسلسلات الهرميةمراجعة - التسلسل الهرمي للموظفينتدرّب بنفسك: Playground لـ Swift