final והיררכיות
חלק מהיחידה תכנות מונחה עצמים במסלול ה-Swift של Coddy. שיעור 25 מתוך 57.
final מונע דריסות נוספות. אי אפשר לדרוס final func באף מחלקת משנה, ואי אפשר לרשת מ־final class כלל:
class Account {
final func id() -> String { "ACC" } // לא ניתן לדרוס אותה
}
final class Receipt { } // לא ניתן ליצור ממנה תת־מחלקה
// class GiftReceipt: Receipt { } // שגיאה: ירושה ממחלקת finalסמנו מתודה ב-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 שמור, סכום = value), לכל אחד מהם אתחול ודריסת amount(for:). apply(to:) עצמה נשארת ב־Discount.
הקוד שסופק קורא את המחיר ואז מחיל הנחות p,10 או f,300, מחיל כל אחת מהן על המחיר ומדפיס 1000 -> 900.
יש לכתוב את הקוד שלך בקבצים Discount.swift, PercentOff.swift ו־FixedOff.swift. הקובץ main.swift מכיל את קוד הקלט/פלט שסופק ואי אפשר לערוך אותו.
נסו בעצמכם
// קוד הקלט/פלט שסופק: יש להשאיר אותו כפי שהוא
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))")
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
תרגלו בעצמכם: Swift אונליין