Menu
Coddy logo textTech

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 final

Contrassegna 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
90

Le 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
eats

Mantieni 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?
challenge icon

Sfida

Facile

Discount 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))")
}
quiz iconMettiti alla prova

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

Esercitati da solo: Playground Swift