Изменяющие методы
Часть раздела Объектно-ориентированное программирование путешествия по 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Задание
ЛегкоЗавершите структуру 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())
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Классы и объекты
Работа с файламиОпределение классовМетоды и selfИнициализаторыКлассы — это ссылкиПовторение — читательский билет4Инкапсуляция
Контроль доступаТолько чтение извнеЗащита состоянияИнициализаторы с возможностью сбояПовторение — банковский счёт7Полиморфизм и обобщения
ПолиморфизмПриведение типовОбобщённые функцииОбобщённые типыПовторение — калькулятор фигур10Паттерны проектирования. Часть 2
Паттерн делегированияПаттерн декораторПаттерн строительПаттерн состояния2Структуры и типы-значения
СтруктурыСемантика значенийИзменяющие методыСтруктура или классПовторение — элемент инвентаря5Наследование
ПодклассыПереопределение методовИнициализаторы и superfinal и иерархииПовторение — иерархия сотрудников8Стандартные протоколы
CustomStringConvertibleEquatableComparableHashableПовторение — пользовательская сортировка11Проект: Управление библиотекой
Книги и читателиВыдача книгПотренируйтесь самостоятельно: Песочница Swift