Menu
Coddy logo textTech

Inicializadores y super

Parte de la sección Programación orientada a objetos del Journey de Swift de Coddy. Lección 24 de 57.

Cuando una subclase añade una propiedad almacenada sin un valor predeterminado, necesita su propio inicializador. Primero establece sus propias propiedades y después llama al inicializador de la superclase 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)")

Salida:

Pip false

El orden importa: las propiedades de la subclase deben tener valores antes de que se ejecute super.init, y las propiedades heredadas solo se pueden usar después. Swift lo comprueba en tiempo de compilación:

init(name: String, canFly: Bool) {
    // print(self.name)      // error: self usado antes de super.init
    self.canFly = canFly     // 1. propiedades propias
    super.init(name: name)   // 2. superclase
    print(self.name)         // 3. ahora se puede usar todo
}

Una vez que una subclase define su propio inicializador, ya no hereda los inicializadores de la superclase. Una subclase también puede sobrescribir un inicializador con los mismos parámetros, marcándolo como 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)

Salida:

0
30

Cada nivel de una jerarquía inicializa su propia parte y entrega el resto a su superclase, de modo que cada propiedad de la cadena recibe un valor exactamente una vez:

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

Salida:

City Cabs: 4 wheels, 5 seats
challenge icon

Desafío

Fácil

Product almacena name y price (en céntimos). Declara la subclase DiscountedProduct con un percent almacenado. Su inicializador recibe name, price y percent, almacena percent y llama a super.init con el precio ya reducido según el porcentaje (redondeado hacia abajo). Un percent fuera del rango 0-100 cuenta como 0. Añade un método label() en DiscountedProduct que devuelva tea: 450 (10% off).

El código proporcionado lee líneas name,price,percent, crea un DiscountedProduct para cada una e imprime label().

Tu código va en Product.swift y DiscountedProduct.swift. main.swift contiene el código proporcionado de entrada/salida y no se puede editar.

Pruébalo tú mismo

// Código de entrada/salida suministrado: déjalo tal como está
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 iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación orientada a objetos

Practica por tu cuenta: Playground de Swift