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 finalMarque 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
90As 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
eatsMantenha 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?Desafio
FácilDiscount 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))")
}
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
1Classes e Objetos
Trabalhando com ArquivosDefinindo ClassesMétodos e selfInicializadoresClasses são ReferênciasRevisão - Cartão da Biblioteca4Encapsulamento
Controle de AcessoSomente Leitura ExternaProtegendo o EstadoInicializadores que Podem FalharRevisão - Conta Bancária7Polimorfismo e Genéricos
PolimorfismoConversão de TiposFunções GenéricasTipos GenéricosRevisão - Calculadora de Formas2Structs e Tipos de Valor
StructsSemântica de ValorMétodos MutáveisStruct ou ClasseRecapitulação - Item de Inventário5Herança
SubclassesSobrescrita de métodosInicializadores e superfinal e hierarquiasRecapitulação - Hierarquia de funcionários8Protocolos Padrão
CustomStringConvertibleEquatableComparableHashableRecapitulação - Ordenação Personalizada11Projeto: Gerenciamento de Biblioteca
Livros e MembrosEmpréstimo de LivrosPratique por conta própria: Playground de Swift