final y jerarquías
Parte de la sección Programación orientada a objetos del Journey de Swift de Coddy. Lección 25 de 57.
final impide futuras sobrescrituras. Una final func no se puede sobrescribir en ninguna subclase, y una final class no puede tener subclases:
class Account {
final func id() -> String { "ACC" } // no se puede sobrescribir
}
final class Receipt { } // no se puede subclasificar
// class GiftReceipt: Receipt { } // error: herencia de una clase finalMarca un método final cuando las subclases no deban cambiarlo, por ejemplo, un método que hace cumplir una regla. Otros métodos aún pueden sobrescribirse para personalizar los detalles:
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]))Salida:
100
90Las jerarquías pueden tener varios niveles. Se busca un método desde la propia clase del objeto hacia arriba, y se ejecuta la primera implementación encontrada:
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())Salida:
swims
eatsMantén las jerarquías poco profundas. Las cadenas profundas son difíciles de seguir, porque el comportamiento de un objeto se distribuye entre muchas clases. Cuando los tipos comparten comportamiento sin una relación es-un, los protocolos (capítulo siguiente) suelen ser la mejor herramienta.
// profundo y frágil
class A { }
class B: A { }
class C: B { }
class D: C { } // ¿qué hereda D, y de dónde?Desafío
FácilDiscount tiene un método final apply(to:) que devuelve el precio menos amount(for:), pero nunca por debajo de 0, y amount(for:) devuelve 0. Declara PercentOff (con percent almacenado, amount = precio por percent / 100) y FixedOff (con value almacenado, amount = value), cada uno con un inicializador y una sobrescritura de amount(for:). apply(to:) permanece en Discount.
El código proporcionado lee el precio y después aplica descuentos p,10 o f,300, aplica cada uno al precio e imprime 1000 -> 900.
Tu código va en Discount.swift, PercentOff.swift y FixedOff.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) }
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 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
1Clases y objetos
Trabajar con archivosDefinir clasesMétodos y selfInicializadoresLas clases son referenciasRepaso: tarjeta de biblioteca4Encapsulación
Control de accesoSolo lectura desde fueraProtección del estadoInicializadores que pueden fallarRepaso - Cuenta bancaria7Polimorfismo y genéricos
PolimorfismoConversión de tiposFunciones genéricasTipos genéricosRepaso - Calculadora de formas2Structs y tipos por valor
StructsSemántica de valoresMétodos mutablesStruct o claseRepaso - elemento del inventario5Herencia
SubclasesSobrescritura de métodosInicializadores y superfinal y jerarquíasRepaso: jerarquía de empleados8Protocolos estándar
CustomStringConvertibleEquatableComparableHashableRepaso - Ordenamiento personalizado11Proyecto: Gestión de bibliotecas
Libros y miembrosPréstamo de librosPractica por tu cuenta: Playground de Swift