Observadores de propiedades
Parte de la sección Programación orientada a objetos del Journey de Swift de Coddy. Lección 13 de 57.
Un observador de propiedades ejecuta código cada vez que cambia una propiedad almacenada. didSet se ejecuta justo después de almacenar el nuevo valor, y dentro de él oldValue contiene el valor anterior:
class Player {
var score = 0 {
didSet {
print("score \(oldValue) -> \(score)")
}
}
}
let p = Player()
p.score = 10
p.score += 5Salida:
score 0 -> 10
score 10 -> 15willSet se ejecuta antes del cambio, con el valor entrante como newValue. Los observadores no se ejecutan cuando la propiedad recibe su valor inicial:
struct Thermostat {
var target = 20 {
willSet { print("changing to \(newValue)") }
didSet { print("changed from \(oldValue)") }
}
}
var t = Thermostat()
t.target = 22Salida:
changing to 22
changed from 20didSet es un buen lugar para mantener válido un valor. Asignar a la propiedad dentro de su propio didSet no vuelve a activar el observador:
struct Volume {
var level = 5 {
didSet {
if level > 10 { level = 10 }
if level < 0 { level = 0 }
}
}
}
var v = Volume()
v.level = 42
print(v.level)
v.level = -3
print(v.level)Salida:
10
0Los observadores también pueden mantener un historial o actualizar un estado relacionado, lo que mantiene esa lógica junto a la propiedad en lugar de dispersarla por el código:
class Account {
var history: [Int] = []
var balance = 0 {
didSet { history.append(balance - oldValue) }
}
}
let a = Account()
a.balance = 100
a.balance = 70
print(a.history)Salida:
[100, -30]Desafío
FácilCompleta la clase Tank. Su propiedad almacenada level debe mantenerse entre 0 y capacity: añade un didSet que corrija los valores fuera de ese rango y que añada una advertencia low a alerts siempre que el nivel corregido termine por debajo del 20 % de la capacidad (y el nivel anterior no fuera bajo).
El código proporcionado lee la capacidad y después cambia +n o -n. Imprime el nivel después de cada cambio y finalmente alerts: con el número de advertencias.
Tu código va en Tank.swift. main.swift contiene el código de entrada/salida proporcionado 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 tank = Tank(capacity: Int(input[0])!)
for cmd in input.dropFirst() {
let n = Int(cmd.dropFirst())!
tank.level += cmd.hasPrefix("+") ? n : -n
print(tank.level)
}
print("alerts: \(tank.alerts.count)")
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 libros3Propiedades en profundidad
Propiedades calculadasObservadores de propiedadesMiembros estáticosEnumeraciones con métodosRepaso - Registro de temperaturaPractica por tu cuenta: Playground de Swift