Перейти к содержимому
Теория · Структуры · урок 8 из 9

Структура копируется

Вернёмся к ксероксу из начала темы. Бланк Point с x: 1 кладут в копировальный аппарат и получают копию. На копии графу x исправляют на 10. Оригинал при этом не меняется: в нём по-прежнему x: 1.

Структура в Swift копируется так же. Посмотрим на код:

SWIFT
struct Point {
    var x: Int
    var y: Int
}

let a = Point(x: 1, y: 2)
var b = a
b.x = 10
print(a.x, b.x) // 1 10

Давайте разберём программу по строкам:

  1. let a = Point(x: 1, y: 2) заполняет бланк-оригинал.
  2. var b = a делает копию: теперь бланков два, и записи на них одинаковые.
  3. b.x = 10 исправляет графу только на копии.
  4. print(a.x, b.x) печатает 1 10: оригинал не изменился.

Обратите внимание: a объявлен через let, а b — через var. У копии своё объявление, поэтому её можно менять, хотя оригинал — константа.

Структура — значимый тип

Как вы уже знаете, массив — значимый тип: присваивание создаёт его независимую копию. Структура тоже значимый тип. Чаще всего её копия появляется в двух случаях:

  • при присваивании: var b = a;
  • при передаче в функцию: параметр получает свою копию экземпляра.

Нажмите «Следующий шаг» и сравнивайте a с b, а потом b с точками внутри функции moved: меняется только тот экземпляр, у которого исправили свойство.

ВживуюОригинал и его копиишаг 1 из 10 · рамок: 1

Константа a — бланк-оригинал с x: 1 и y: 2.

Следите за a: её x не меняется ни на одном шаге

Функция moved получает копию b в параметр p. Параметр — константа, поэтому функция делает ещё одну копию, copy, меняет её и возвращает. После вызова b прежний, а точка с x: 15 лежит в c. Чтобы функция изменила саму переменную того, кто её вызвал, нужны параметр inout и & при вызове.

Здесь картинка с ксероксом неточна. Бумажную копию делают вручную, когда она нужна. Swift копирует структуру сам, при каждом присваивании и передаче в функцию, без отдельной команды «скопировать».

На собеседовании часто спрашивают: что станет с первой структурой, если изменить её копию? Ответ: ничего. Структура — значимый тип, и у копии свои свойства, независимые от оригинала.

Частая ошибка

Точку достали из массива, изменили и ждали, что изменится элемент массива:

SWIFT
var points = [Point(x: 1, y: 2), Point(x: 3, y: 4)]
var first = points[0]
first.x = 10 // ✗
print(points[0].x) // 1

Программа компилируется и печатает 1. Строка var first = points[0] создаёт копию элемента, и first.x = 10 исправляет только её, а элемент в массиве остался прежним. Чтобы изменить сам элемент, пишите через индекс: points[0].x = 10.

Главное

  • Структура — значимый тип: var b = a создаёт независимую копию, и изменения b не видны в a.
  • У копии своё объявление: структуру из let можно скопировать в var и менять.
  • Функция получает свою копию структуры, и изменения внутри функции не трогают переменную снаружи.
  • Переменная получает копию элемента массива; сам элемент меняют через индекс: points[0].x = 10.