Menu
Coddy logo textTech

final i hierarchie

Część sekcji Programowanie obiektowe ścieżki Swift w Coddy. Lekcja 25 z 57.

final uniemożliwia dalsze nadpisywanie. Metody final func nie można nadpisać w żadnej podklasie, a klasy final class nie można w ogóle rozszerzyć przez dziedziczenie:

class Account {
    final func id() -> String { "ACC" }   // nie można przesłonić
}

final class Receipt { }                  // nie można po niej dziedziczyć
// class GiftReceipt: Receipt { }        // błąd: dziedziczenie po klasie final

Oznacz metodę jako final, gdy podklasy nie mogą jej zmieniać, na przykład gdy metoda egzekwuje jakąś regułę. Inne metody nadal można nadpisywać, aby dostosować szczegóły:

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]))

Wynik:

100
90

Hierarchie może mieć kilka poziomów. Metoda jest wyszukiwana od klasy samego obiektu w górę, a uruchamiana jest pierwsza znaleziona implementacja:

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())

Wynik:

swims
eats

Utrzymuj płytkie hierarchie. Głębokie łańcuchy są trudne do prześledzenia, ponieważ zachowanie jednego obiektu jest rozłożone na wiele klas. Gdy typy współdzielą zachowanie, ale nie są ze sobą powiązane relacją „jest”, protokoły (następny rozdział) są zazwyczaj lepszym rozwiązaniem.

// głęboka i krucha
class A { }
class B: A { }
class C: B { }
class D: C { }      // co dziedziczy D i po kim?
challenge icon

Wyzwanie

Łatwy

Discount ma metodę final apply(to:), która zwraca cenę pomniejszoną o amount(for:), ale nie niższą niż 0, a amount(for:) zwraca 0. Zadeklaruj PercentOff (przechowywane percent, kwota = cena razy procent / 100) oraz FixedOff (przechowywane value, kwota = wartość), każdą z inicjalizatorem i nadpisaniem amount(for:). Sama metoda apply(to:) pozostaje w Discount.

Dostarczony kod odczytuje cenę, a następnie rabaty p,10 lub f,300, stosuje każdy z nich do ceny i wypisuje 1000 -> 900.

Twój kod umieść w plikach Discount.swift, PercentOff.swift i FixedOff.swift. main.swift zawiera dostarczony kod wejścia/wyjścia i nie można go edytować.

Spróbuj swoich sił

// Dostarczony kod wejścia/wyjścia: pozostaw go bez zmian
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 iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Edytor online Swift