Menu
Coddy logo textTech

Métodos mutables

Parte de la sección Programación orientada a objetos del Journey de Swift de Coddy. Lección 9 de 57.

Un método de una estructura que cambia una propiedad debe marcarse como mutating. Sin esta palabra clave, el método no se compila, porque los métodos de un tipo de valor tratan self como una constante:

struct Counter {
    var count = 0

    mutating func increment() {
        count += 1
    }
}

var c = Counter()
c.increment()
c.increment()
print(c.count)

Salida:

2

Un método mutante solo se puede llamar en una var. En una constante let, la llamada no se compila, porque todo el valor es fijo:

var a = Counter()
a.increment()        // bien

let b = Counter()
// b.increment()     // error: b es una constante let

Los métodos que solo leen propiedades no producen mutaciones y también funcionan con constantes. Un buen diseño mantiene los cambios en unos pocos métodos mutantes:

struct Stack {
    var items: [Int] = []

    mutating func push(_ x: Int) { items.append(x) }
    mutating func pop() -> Int? { items.popLast() }
    func peek() -> Int? { items.last }
}

var s = Stack()
s.push(3)
s.push(8)
print(s.pop() ?? -1)
print(s.peek() ?? -1)

Salida:

8
3

Un método mutador puede reemplazar self por completo, lo cual resulta útil para restablecer un valor:

struct Score {
    var points = 0
    var bonus = 0

    mutating func reset() {
        self = Score()
    }
}

var s = Score(points: 10, bonus: 3)
s.reset()
print(s.points + s.bonus)

Salida:

0
challenge icon

Desafío

Fácil

Completa la estructura Wallet. add(_:) y spend(_:) son mutantes: spend resta solo cuando queda suficiente dinero y devuelve si lo hizo. report() no es mutante y devuelve balance 40.

El código proporcionado lee los comandos +n y -n, los aplica a una única var wallet, imprime denied cuando se rechaza un gasto y, finalmente, imprime report().

Tu código va en Wallet.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 cual
var input: [String] = []
while let line = readLine() { input.append(line) }
var wallet = Wallet()
for cmd in input {
    let amount = Int(cmd.dropFirst())!
    if cmd.hasPrefix("+") {
        wallet.add(amount)
    } else if !wallet.spend(amount) {
        print("denied")
    }
}
print(wallet.report())
quiz iconPonte a prueba

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

Practica por tu cuenta: Playground de Swift