Menu
Coddy logo textTech

Initialisierer und super

Teil des Abschnitts Objektorientierte Programmierung der Swift-Journey von Coddy. Lektion 24 von 57.

Wenn eine Unterklasse eine gespeicherte Eigenschaft ohne Standardwert hinzufügt, benötigt sie ihren eigenen Initialisierer. Sie setzt zuerst ihre eigenen Eigenschaften und ruft dann den Initialisierer der Oberklasse mit super.init(...) auf:

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

Ausgabe:

Pip false

Die Reihenfolge ist wichtig: Die Eigenschaften der Unterklasse müssen Werte haben, bevor super.init ausgeführt wird, und geerbte Eigenschaften können erst danach verwendet werden. Swift überprüft dies zur Kompilierzeit:

init(name: String, canFly: Bool) {
    // print(self.name)      // Fehler: self vor super.init verwendet
    self.canFly = canFly     // 1. eigene Eigenschaften
    super.init(name: name)   // 2. Superklasse
    print(self.name)         // 3. jetzt kann alles verwendet werden
}

Sobald eine Unterklasse ihren eigenen Initialisierer definiert, erbt sie die Initialisierer der Oberklasse nicht mehr. Eine Unterklasse kann einen Initialisierer mit denselben Parametern auch überschreiben, indem sie ihn als override init kennzeichnet:

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)

Ausgabe:

0
30

Jede Ebene einer Hierarchie initialisiert ihren eigenen Teil und übergibt den Rest an ihre Oberklasse, sodass jede Eigenschaft in der Kette genau einmal einen Wert erhält:

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

Ausgabe:

City Cabs: 4 wheels, 5 seats
challenge icon

Aufgabe

Einfach

Product speichert name und price (in Cent). Deklariere die Unterklasse DiscountedProduct mit einem gespeicherten percent. Ihr Initialisierer nimmt name, price und percent entgegen, speichert percent und ruft super.init mit dem bereits um den Prozentsatz reduzierten Preis (abgerundet) auf. Ein percent außerhalb von 0–100 zählt als 0. Füge in DiscountedProduct eine Methode label() hinzu, die tea: 450 (10% off) zurückgibt.

Der bereitgestellte Code liest Zeilen im Format name,price,percent, erstellt für jede eine DiscountedProduct-Instanz und gibt label() aus.

Dein Code gehört in Product.swift und DiscountedProduct.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) }
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 iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung

Übe selbstständig: Swift-Playground