final e gerarchie
Fa parte della sezione Programmazione orientata agli oggetti del percorso Swift di Coddy. Lezione 25 di 57.
final impedisce ulteriori override. Una final func non può essere sottoposta a override in nessuna sottoclasse e una final class non può essere sottoclassata:
class Account {
final func id() -> String { "ACC" } // non può essere ridefinito
}
final class Receipt { } // non può essere estesa tramite una sottoclasse
// class GiftReceipt: Receipt { } // errore: ereditarietà da una classe finalContrassegna un metodo come final quando le sottoclassi non devono modificarlo, per esempio un metodo che applica una regola. Gli altri metodi possono comunque essere sovrascritti per personalizzare i dettagli:
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]))Output:
100
90Le gerarchie possono avere diversi livelli. Un metodo viene cercato a partire dalla classe dell'oggetto e risalendo la gerarchia, e viene eseguita la prima implementazione trovata:
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())Output:
swims
eatsMantieni le gerarchie poco profonde. Le catene profonde sono difficili da seguire, perché il comportamento di un oggetto è distribuito su molte classi. Quando i tipi condividono un comportamento senza una relazione is-a, i protocolli (prossimo capitolo) sono di solito lo strumento migliore.
// profondo e fragile
class A { }
class B: A { }
class C: B { }
class D: C { } // che cosa eredita D e da dove?Sfida
FacileDiscount ha un metodo final apply(to:) che restituisce il prezzo meno amount(for:), senza però scendere mai sotto 0, e amount(for:) restituisce 0. Dichiara PercentOff (con percent memorizzato, importo = prezzo per percento / 100) e FixedOff (con value memorizzato, importo = value), ciascuno con un inizializzatore e un override di amount(for:). apply(to:) rimane in Discount.
Il codice fornito legge il prezzo e poi gli sconti p,10 o f,300, applica ciascuno al prezzo e stampa 1000 -> 900.
Il tuo codice va in Discount.swift, PercentOff.swift e FixedOff.swift. main.swift contiene il codice di input/output fornito e non può essere modificato.
Provalo tu
// Supplied input/output code: keep it as it is
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))")
}
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Programmazione orientata agli oggetti
1Classi e oggetti
Lavorare con i fileDefinire le classiMetodi e selfInizializzatoriLe classi sono riferimentiRiepilogo - Tessera della biblioteca4Incapsulamento
Controllo degli accessiSola lettura dall’esternoProteggere lo statoInizializzatori che possono fallireRiepilogo - Conto bancario7Polimorfismo e tipi generici
PolimorfismoCasting dei tipiFunzioni genericheTipi genericiRipasso - Calcolatore di forme2Struct e tipi valore
Le structSemantica dei valoriMetodi mutantiStruct o classeRiepilogo - Articolo di inventario5Ereditarietà
SottoclassiSovrascrivere i metodiInizializzatori e superfinal e gerarchieRiepilogo - Gerarchia dei dipendenti8Protocolli standard
CustomStringConvertibleEquatableComparableHashableRiepilogo - Ordinamento personalizzato11Progetto: Gestione della biblioteca
Libri e utentiPrestito dei libriEsercitati da solo: Playground Swift