Menu
Coddy logo textTech

Inizializzatori e super

Fa parte della sezione Programmazione orientata agli oggetti del percorso Swift di Coddy. Lezione 24 di 57.

Quando una sottoclasse aggiunge una proprietà memorizzata senza un valore predefinito, ha bisogno di un proprio inizializzatore. Prima imposta le proprie proprietà e poi chiama l'inizializzatore della superclasse con 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)")

Output:

Pip false

L'ordine è importante: le proprietà della sottoclasse devono avere dei valori prima che venga eseguito super.init, e le proprietà ereditate possono essere usate solo dopo. Swift verifica questo in fase di compilazione:

init(name: String, canFly: Bool) {
    // print(self.name)      // errore: self usato prima di super.init
    self.canFly = canFly     // 1. proprietà proprie
    super.init(name: name)   // 2. superclasse
    print(self.name)         // 3. ora si può usare tutto
}

Una volta che una sottoclasse definisce il proprio inizializzatore, non eredita più quelli della superclasse. Una sottoclasse può anche eseguire l'override di un inizializzatore con gli stessi parametri, contrassegnandolo come 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)

Output:

0
30

Ogni livello di una gerarchia inizializza la propria parte e delega il resto alla sua superclasse, così ogni proprietà della catena riceve un valore esattamente una volta:

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

Output:

City Cabs: 4 wheels, 5 seats
challenge icon

Sfida

Facile

Product memorizza name e price (in centesimi). Dichiara la sottoclasse DiscountedProduct con una proprietà memorizzata percent. Il suo inizializzatore accetta name, price e percent, memorizza percent e chiama super.init con il prezzo già ridotto della percentuale (arrotondato per difetto). Un valore di percent al di fuori dell'intervallo 0-100 viene considerato come 0. Aggiungi un metodo label() in DiscountedProduct che restituisca tea: 450 (10% off).

Il codice fornito legge righe nel formato name,price,percent, crea un DiscountedProduct per ciascuna e stampa label().

Il tuo codice va inserito in Product.swift e DiscountedProduct.swift. main.swift contiene il codice di input/output fornito e non può essere modificato.

Provalo tu

// Codice di input/output fornito: lascialo così com'è
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 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