Menu
Coddy logo textTech

Inicializadores e super

Parte da seção Programação Orientada a Objetos do Journey de Swift da Coddy. Lição 24 de 57.

Quando uma subclasse adiciona uma propriedade armazenada sem um valor padrão, ela precisa de seu próprio inicializador. Primeiro, ela define suas próprias propriedades e, em seguida, chama o inicializador da superclasse com 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)")

Saída:

Pip false

A ordem é importante: as propriedades da subclasse devem ter valores antes que super.init seja executado, e as propriedades herdadas só podem ser usadas depois disso. Swift verifica isso em tempo de compilação:

init(name: String, canFly: Bool) {
    // print(self.name)      // erro: self usado antes de super.init
    self.canFly = canFly     // 1. propriedades próprias
    super.init(name: name)   // 2. superclasse
    print(self.name)         // 3. agora tudo pode ser usado
}

Quando uma subclasse define seu próprio inicializador, ela deixa de herdar os inicializadores da superclasse. Uma subclasse também pode substituir um inicializador com os mesmos parâmetros, marcando-o 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)

Saída:

0
30

Cada nível de uma hierarquia inicializa sua própria parte e passa o restante para sua superclasse, de modo que cada propriedade da cadeia receba um valor exatamente uma 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")

Saída:

City Cabs: 4 wheels, 5 seats
challenge icon

Desafio

Fácil

Product armazena name e price (em centavos). Declare a subclasse DiscountedProduct com um percent armazenado. Seu inicializador recebe name, price e percent, armazena percent e chama super.init com o preço já reduzido pela porcentagem (arredondado para baixo). Um percent fora do intervalo de 0 a 100 conta como 0. Adicione um método label() em DiscountedProduct que retorne tea: 450 (10% off).

O código fornecido lê linhas name,price,percent, cria um DiscountedProduct para cada uma e imprime label().

Seu código deve ser inserido em Product.swift e DiscountedProduct.swift. main.swift contém o código fornecido de entrada/saída e não pode ser editado.

Experimente você mesmo

// Código de entrada/saída fornecido: mantenha-o 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 iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos

Pratique por conta própria: Playground de Swift