Menu
Coddy logo textTech

Inicjalizatory i super

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

Gdy podklasa dodaje przechowywaną właściwość bez wartości domyślnej, potrzebuje własnego inicjalizatora. Najpierw ustawia własne właściwości, a następnie wywołuje inicjalizator nadklasy za pomocą super.init(...):

class Animal {
    let name: String
    init(name: String) { self.name = name }
}

class Bird: Animal {
    let canFly: Bool

    init(name: String, canFly: Bool) {
        self.canFly = canFly
        super.init(name: name)
    }
}

let p = Bird(name: "Pip", canFly: false)
print("\(p.name) \(p.canFly)")

Wynik:

Pip false

Kolejność ma znaczenie: właściwości podklasy muszą mieć wartości, zanim zostanie wywołane super.init, a z odziedziczonych właściwości można korzystać dopiero po tym wywołaniu. Swift sprawdza to w czasie kompilacji:

init(name: String, canFly: Bool) {
    // print(self.name)      // błąd: self użyte przed super.init
    self.canFly = canFly     // 1. własne właściwości
    super.init(name: name)   // 2. klasa nadrzędna
    print(self.name)         // 3. teraz można używać wszystkiego
}

Gdy podklasa definiuje własny inicjalizator, nie dziedziczy już inicjalizatorów nadklasy. Podklasa może też przesłonić inicjalizator z tymi samymi parametrami, oznaczając go jako override init:

class Timer {
    var seconds: Int
    init(seconds: Int) { self.seconds = seconds }
}

class SafeTimer: Timer {
    override init(seconds: Int) {
        super.init(seconds: max(0, seconds))
    }
}

print(SafeTimer(seconds: -5).seconds)
print(SafeTimer(seconds: 30).seconds)

Wynik:

0
30

Każdy poziom hierarchii inicjalizuje swoją część i przekazuje resztę swojej nadklasie, dzięki czemu każda właściwość w łańcuchu otrzymuje wartość dokładnie raz:

class Vehicle {
    let wheels: Int
    init(wheels: Int) { self.wheels = wheels }
}

class Car: Vehicle {
    let seats: Int
    init(seats: Int) {
        self.seats = seats
        super.init(wheels: 4)
    }
}

class Taxi: Car {
    let company: String
    init(company: String) {
        self.company = company
        super.init(seats: 5)
    }
}

let t = Taxi(company: "City Cabs")
print("\(t.company): \(t.wheels) wheels, \(t.seats) seats")

Wynik:

City Cabs: 4 wheels, 5 seats
challenge icon

Wyzwanie

Łatwy

Product przechowuje name i price (w centach). Zadeklaruj podklasę DiscountedProduct z przechowywanym percent. Jej inicjalizator przyjmuje name, price i percent, przechowuje percent i wywołuje super.init z ceną już obniżoną o procent (zaokrągloną w dół). Wartość percent spoza zakresu 0-100 jest traktowana jako 0. Dodaj metodę label() w DiscountedProduct, która zwraca tea: 450 (10% off).

Dostarczony kod odczytuje wiersze name,price,percent, tworzy dla każdego obiektu DiscountedProduct i wypisuje label().

Twój kod umieść w plikach Product.swift i DiscountedProduct.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) }
for line in input {
    let p = line.split(separator: ",").map { String($0) }
    let item = DiscountedProduct(name: p[0], price: Int(p[1])!, percent: Int(p[2])!)
    print(item.label())
}
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