Ответ
Ключевое слово mutating позволяет методу модифицировать свойства value-типа (структуры или перечисления). При вызове такого метода для var экземпляра, создается новая копия структуры с измененными значениями, которая затем заменяет исходный экземпляр.
Пример:
struct Point {
var x: Int
var y: Int
// mutating метод изменяет свойства
mutating func moveBy(x deltaX: Int, y deltaY: Int) {
x += deltaX
y += deltaY
}
}
var point = Point(x: 0, y: 0)
point.moveBy(x: 5, y: 5) // point теперь Point(x: 5, y: 5)
Ключевые аспекты:
- Только для
var: Вызовmutatingметода для экземпляра, объявленного черезlet, вызовет ошибку компиляции. - Семантика value-типа: Изменение происходит через подмену всего экземпляра, что соответствует поведению value-типов.
- Оптимизация (Copy-on-Write): Для сложных структур (например,
Array) Swift использует механизм Copy-on-Write, чтобы избежать излишнего копирования, пока данные не будут реально изменены.
Ответ 18+ 🔞
Слушай, вот объясняю тебе как для дебила, но ты не обижайся, а то я сам от этого mutating чуть не поседел. Представь, что структура — это как твой паспорт, бумажная ксерокопия. Настоящий, блядь, value-тип.
Вот ты с этой бумажкой ходишь. Захочешь в графе «прописка» исправить «Москва» на «Магадан» — и что? Взял ручку, зачеркнул? Нихуя! Это ж копия, её менять низя. Надо взять новый бланк, переписать всё как было, но в графе «прописка» уже написать «Магадан». И старую бумажку — в утиль, а новую в руки. Вот этот процесс создания новой копии с изменениями и есть mutating метод, ёпта.
struct Point {
var x: Int
var y: Int
// Смотри, вот этот метод — он как раз таки мутирует, то есть делает новую копию
mutating func moveBy(x deltaX: Int, y deltaY: Int) {
x += deltaX // Тут меняем
y += deltaY // И тут меняем
}
}
var point = Point(x: 0, y: 0) // Объявил через `var`, потому что с `let` нихуя не выйдет
point.moveBy(x: 5, y: 5) // Вжух! point теперь Point(x: 5, y: 5)
А теперь главные моменты, чтобы ты не облажался:
-
Только для
var, ёбаный насос! Если твой экземпляр объявлен черезlet— всё, пиши пропало. Компилятор тебе такую ошибку влепит, что мало не покажется.let— это константа, её менять нельзя, даже черезmutating. Это как прибить паспорт гвоздём к столу — хоть ты новый и нарисуй, оторвать-то старый нельзя. -
Семантика, блядь, value-типа. Всё честно. Мы не лезем внутрь и не ковыряемся в памяти. Мы делаем новую хуйню и подменяем старую. Чисто, прозрачно, без подвохов.
-
А вот тут магия (Copy-on-Write). Чтобы не копировать гигабайты данных просто так, Swift включает режим хитрожопости. Возьмём, например, массив (
Array). Пока ты его не начал менять — все переменные могут тихо ссылаться на одни и те же данные в памяти. Но как только ты черезmutatingметод попытаешься что-то там пошатать — только тогда Swift сгоряча создаст отдельную, настоящую копию данных. Оптимизация, блять, чтобы не тратить ресурсы зря. Умно, да?