Menu
Coddy logo textTech

final e hierarquias

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

final impede novas substituições. Uma final func não pode ser substituída em nenhuma subclasse, e uma final class não pode ser herdada de forma alguma:

class Account {
    final func id() -> String { "ACC" }   // não pode ser sobrescrito
}

final class Receipt { }                  // não pode ser subclassificado
// class GiftReceipt: Receipt { }        // erro: herança de uma classe final

Marque um método final quando as subclasses não devem alterá-lo, por exemplo, um método que impõe uma regra. Outros métodos ainda podem ser sobrescritos para personalizar detalhes:

class Checkout {
    final func total(_ prices: [Int]) -> Int {
        let sum = prices.reduce(0, +)
        return sum - discount(sum)
    }
    func discount(_ sum: Int) -> Int { 0 }
}

class SaleCheckout: Checkout {
    override func discount(_ sum: Int) -> Int { sum / 10 }
}

print(Checkout().total([50, 50]))
print(SaleCheckout().total([50, 50]))

Saída:

100
90

As hierarquias podem ter vários níveis. Um método é procurado a partir da própria classe do objeto, subindo pela hierarquia, e a primeira implementação encontrada é executada:

class Animal {
    func move() -> String { "moves" }
    func eat() -> String { "eats" }
}
class Bird: Animal {
    override func move() -> String { "flies" }
}
class Penguin: Bird {
    override func move() -> String { "swims" }
}

let p = Penguin()
print(p.move())
print(p.eat())

Saída:

swims
eats

Mantenha as hierarquias superficiais. Cadeias profundas são difíceis de acompanhar, porque o comportamento de um objeto fica distribuído por muitas classes. Quando os tipos compartilham comportamento sem uma relação de “é um”, os protocolos (próximo capítulo) geralmente são a melhor ferramenta.

// profunda e frágil
class A { }
class B: A { }
class C: B { }
class D: C { }      // o que D herda, e de onde?
challenge icon

Desafio

Fácil

Discount tem um método final apply(to:) que retorna o preço menos amount(for:), mas nunca abaixo de 0, e amount(for:) retorna 0. Declare PercentOff (com percent armazenado, amount = preço vezes percent / 100) e FixedOff (com value armazenado, amount = value), cada um com um inicializador e uma sobrescrita de amount(for:). O próprio apply(to:) permanece em Discount.

O código fornecido lê o preço e, em seguida, aplica os descontos p,10 ou f,300, aplica cada um ao preço e imprime 1000 -> 900.

Seu código deve estar em Discount.swift, PercentOff.swift e FixedOff.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) }
let price = Int(input[0])!
for line in input.dropFirst() {
    let p = line.split(separator: ",").map(String.init)
    let d: Discount = p[0] == "p" ? PercentOff(percent: Int(p[1])!) : FixedOff(value: Int(p[1])!)
    print("\(price) -> \(d.apply(to: price))")
}
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