Структуры
Чему вы научитесь:
- описывать свой тип структурой: свойства, значения по умолчанию, создание экземпляра;
- писать методы и объяснять, зачем методу нужно слово
mutating; - добавлять вычисляемые свойства, наблюдатели
willSetиdidSet, свойinitиstatic; - объяснять, почему изменение копии структуры не трогает оригинал.

Представьте бумажный бланк. В шапке напечатано название Point, ниже две графы с подписями: x и y. Пустой бланк — это образец: он говорит, какие графы есть и что в них писать. Заполненный бланк хранит данные: в графе x стоит 1, в графе y — 2.
Бланк можно отксерокопировать. На копии графу x зачёркивают и пишут 10, а на оригинале по-прежнему x: 1. Бланки, заполненные по одному образцу, живут каждый сам по себе.
Зачем такой бланк в программе? Точка на плоскости — это два числа, и их можно держать в двух переменных, x и y. Но когда точек станет 10, переменных будет 20, и придётся следить, какой y относится к какому x. Удобнее собрать оба числа под одним именем. Для этого в Swift есть структуры:
struct Point {
var x: Int
var y: Int
}
let start = Point(x: 1, y: 2)
print(start.x) // 1
print(start.y) // 2
print(start) // Point(x: 1, y: 2)Давайте разберём программу по шагам:
- Строки от
structдо закрывающей фигурной скобки описывают образец бланкаPoint. Сами по себе они ничего не создают. Point(x: 1, y: 2)заполняет новый бланк: в графуxпишет1, в графуy—2. Готовый бланк попадает в константуstart.start.xиstart.yчитают графы через точку, и программа печатает1и2.print(start)печатает бланк целиком: имя типа и все графы со значениями.
Объявление структуры
Структура — это свой тип, который собирает несколько значений под одним именем. Объявление struct Point состоит из трёх частей:
struct— ключевое слово, с которого начинается объявление;Point— имя нового типа; имена типов пишут с большой буквы, какIntиString;- фигурные скобки, а в них — графы бланка, каждая со своим именем и типом.
Графы структуры — это её свойства: их, как и у перечислений, читают через точку без скобок. Но свойство структуры хранит значение, и объявляют его как обычную переменную или константу: var x: Int.
Новым типом пользуются так же, как Int или String. Можно объявить константу типа Point, передать точку в функцию или сложить несколько точек в массив [Point].
Создание экземпляра
Конкретное значение типа Point, заполненный бланк, называют экземпляром структуры. Чтобы создать экземпляр, пишут имя типа, а в скобках — значения всех свойств с метками, как аргументы при вызове функции. Swift даёт структуре такой способ создания сам: писать для него ничего не нужно.
Правила у него такие:
- метки совпадают с именами свойств:
x:иy:; - порядок тот же, что в объявлении:
Point(y: 2, x: 1)не скомпилируется с ошибкойargument 'x' must precede argument 'y'; - значение нужно каждому свойству:
Point(x: 1)даёт ошибкуmissing argument for parameter 'y' in call.
Здесь картинка с бланком неточна. Бумажный бланк можно сдать с пустой графой, а у экземпляра структуры заполнены все свойства. Swift не создаст Point, пока не узнает и x, и y.
Значения по умолчанию
Иногда в бланке уже напечатано значение, и его исправляют, только когда нужно. В структуре такое значение пишут прямо в объявлении свойства:
struct Alarm {
var hour = 7
var minute = 30
}
let usual = Alarm()
let early = Alarm(hour: 6)
print(usual) // Alarm(hour: 7, minute: 30)
print(early) // Alarm(hour: 6, minute: 30)Свойство со значением по умолчанию при создании можно пропустить:
Alarm()берёт оба значения по умолчанию:7часов и30минут;Alarm(hour: 6)задаёт час, а минуты оставляет по умолчанию.
Тип свойств здесь не указан: Swift выводит его из значения, как у обычной переменной.
Чтение и изменение через точку
Свойство читают через точку: start.x. Через точку же его меняют, если экземпляр хранится в переменной var:
var finish = Point(x: 1, y: 2)
finish.x = 10
print(finish) // Point(x: 10, y: 2)finish.x = 10 исправляет одну графу, а y остаётся прежним.
Менять свойство можно, только если это разрешают два объявления сразу:
- экземпляр объявлен через
var: у экземпляра вletнельзя переписать ни одно свойство; - само свойство объявлено через
var: свойствоletне изменится даже у экземпляра вvar.
Частая ошибка
Свойство поменяли у экземпляра, объявленного через let:
start.x = 10 // ✗error: cannot assign to property: 'start' is a 'let' constantПрограмма не компилируется. Константа start — запечатанный бланк: менять нельзя ни его целиком, ни отдельные графы, хотя x в Point объявлен через var. Если бланк нужно исправлять, объявите экземпляр через var, как finish.
Главное
- Структура собирает несколько значений под одним именем: после
structидут имя типа и свойства в фигурных скобках. - Экземпляр создают с метками всех свойств по порядку:
Point(x: 1, y: 2); свойство со значением по умолчанию можно пропустить. - Свойство читают и меняют через точку:
finish.x = 10. - Экземпляр в
letне меняется совсем: ни одно его свойство переписать нельзя.