final und Hierarchien
Teil des Abschnitts Objektorientierte Programmierung der Swift-Journey von Coddy. Lektion 25 von 57.
final verhindert weiteres Überschreiben. Eine final func kann in keiner Unterklasse überschrieben werden, und eine final class kann überhaupt nicht als Basisklasse verwendet werden:
class Account {
final func id() -> String { "ACC" } // kann nicht überschrieben werden
}
final class Receipt { } // kann nicht unterklassifiziert werden
// class GiftReceipt: Receipt { } // error: Vererbung von einer finalen KlasseMarkiere eine Methode mit final, wenn Unterklassen sie nicht ändern dürfen, beispielsweise eine Methode, die eine Regel durchsetzt. Andere Methoden können weiterhin überschrieben werden, um Details anzupassen:
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]))Ausgabe:
100
90Hierarchien können mehrere Ebenen haben. Eine Methode wird von der eigenen Klasse des Objekts aufwärts gesucht, und die erste gefundene Implementierung wird ausgeführt:
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())Ausgabe:
swims
eatsHalte Hierarchien flach. Tiefe Ketten sind schwer nachzuvollziehen, weil das Verhalten eines Objekts über viele Klassen verteilt ist. Wenn Typen Verhalten ohne eine Is-a-Beziehung gemeinsam nutzen, sind Protokolle (nächstes Kapitel) meist das bessere Werkzeug.
// tief und fragil
class A { }
class B: A { }
class C: B { }
class D: C { } // was erbt D, und von wo?Aufgabe
EinfachDiscount verfügt über eine final-Methode apply(to:), die den Preis minus amount(for:) zurückgibt, jedoch niemals weniger als 0, und amount(for:) gibt 0 zurück. Deklariere PercentOff (gespeichertes percent, Betrag = Preis mal Prozent / 100) und FixedOff (gespeichertes value, Betrag = value), jeweils mit einem Initialisierer und einer Überschreibung von amount(for:). apply(to:) selbst bleibt in Discount.
Der bereitgestellte Code liest den Preis ein und wendet anschließend Rabatte in Form von p,10 oder f,300 an, wendet jeden davon auf den Preis an und gibt 1000 -> 900 aus.
Dein Code gehört in Discount.swift, PercentOff.swift und FixedOff.swift. main.swift enthält den bereitgestellten Eingabe-/Ausgabecode und darf nicht bearbeitet werden.
Probier es selbst
// Gelieferter Ein-/Ausgabecode: belasse ihn wie er ist
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))")
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Klassen und Objekte
Arbeiten mit DateienKlassen definierenMethoden und selfInitialisiererKlassen sind ReferenzenRückblick – Bibliotheksausweis4Kapselung
ZugriffskontrolleVon außen schreibgeschütztZustand schützenFehlschlagende InitialisiererRückblick – Bankkonto7Polymorphismus und Generika
PolymorphismusTypumwandlungGenerische FunktionenGenerische TypenZusammenfassung – Shape-Rechner2Strukturen und Werttypen
StrukturenWertsemantikVerändernde MethodenStruktur oder KlasseZusammenfassung – Inventarelement5Vererbung
UnterklassenMethoden überschreibenInitialisierer und superfinal und HierarchienRückblick – Mitarbeiterhierarchie8Standardprotokolle
CustomStringConvertibleEquatableComparableHashableRückblick – Benutzerdefiniertes Sortieren11Projekt: Bibliotheksverwaltung
Bücher und MitgliederBücher ausleihenÜbe selbstständig: Swift-Playground