Menu
Coddy logo textTech

Изменяющие методы

Часть раздела Объектно-ориентированное программирование путешествия по Swift на Coddy. Урок 9 из 57.

Метод структуры, изменяющий свойство, должен быть помечен как mutating. Без этого ключевого слова метод не компилируется, поскольку методы типа-значения рассматривают self как константу:

struct Counter {
    var count = 0

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

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

Вывод:

2

Мутирующий метод можно вызвать только для var. Для константы let вызов не компилируется, потому что всё значение является неизменяемым:

var a = Counter()
a.increment()        // нормально

let b = Counter()
// b.increment()     // ошибка: b является константой let

Методы, которые только читают свойства, не изменяют состояние и также работают с константами. Хороший дизайн сосредотачивает изменения в нескольких методах, изменяющих состояние:

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)

Вывод:

8
3

Мутирующий метод может полностью заменить self, что удобно для сброса значения:

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)

Вывод:

0
challenge icon

Задание

Легко

Завершите структуру Wallet. Методы add(_:) и spend(_:) изменяют состояние: spend вычитает сумму только при наличии достаточного остатка и возвращает, произошло ли вычитание. Метод report() не изменяет состояние и возвращает balance 40.

Предоставленный код считывает команды +n и -n, применяет их к одному кошельку var, выводит denied при отклонённой трате и в конце выводит report().

Ваш код должен находиться в Wallet.swift. В main.swift содержится предоставленный код ввода/вывода, и его нельзя изменять.

Попробуйте сами

// Предоставленный код ввода/вывода: оставьте его как есть
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 iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Песочница Swift