Как изменить свойство структуры в Swift?

Ответ

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

Почему это необходимо? Структуры в Swift — value-типы. При вызове метода создается копия структуры, и без mutating изменения не сохранятся.

Пример корректного изменения:

struct Point {
    var x: Int
    var y: Int

    // Метод ДОЛЖЕН быть mutating
    mutating func moveBy(x deltaX: Int, y deltaY: Int) {
        x += deltaX
        y += deltaY
    }
}

// Только переменная (var), не константа (let)
var point = Point(x: 0, y: 0)
point.moveBy(x: 5, y: 5) // Теперь point.x = 5, point.y = 5

Что нельзя делать:

struct Point {
    var x: Int

    // Ошибка компиляции: метод не mutating
    func increment() {
        x += 1 // ❌ Cannot assign to property: 'self' is immutable
    }
}

let point = Point(x: 0)
point.x = 5 // ❌ Cannot assign to property: 'point' is a 'let' constant

Практические рекомендации:

  1. Используйте mutating для методов, изменяющих любые свойства
  2. Структура должна быть объявлена как var, а не let
  3. Для вычисляемых свойств используйте mutating get если свойство изменяет self
  4. Рассмотрите создание новой структуры вместо мутации для иммутабельных данных

Ответ 18+ 🔞

А, слушай, вот этот момент в Swift про структуры — он многих, блядь, в ступор вгоняет, честно. Сидят такие, пытаются свойство поменять, а компилятор им — «чё ты, сука, делаешь, я тебя не понимаю». И начинается: «ну я же просто x увеличить хочу, что за хуйня?».

А вся соль в том, что структура — это не объект, блядь. Это value-тип, то есть, грубо говоря, копия. Представь, ты вызываешь метод у точки. Без mutating тебе подсовывают её ксерокс, ты в этой копии что-то накарябал, а оригинал, блядь, как был нетронутым, так и остался. И компилятор, такой хитрожопый, спрашивает: «Ты чё, мудила, думал, что так сработает?».

Вот поэтому и нужен этот самый mutating. Это как крикнуть системе: «Эй, ёпта, я тут буду оригинал пинать, приготовься!». И система разрешает, но с условием: сама структура должна быть var, а не let. Потому что если она константа, то это уже, блядь, священная корова, её трогать низя.

Смотри, как правильно, чтобы не было мудацких ошибок:

struct Point {
    var x: Int
    var y: Int

    // Без этого mutating — нихуя не выйдет, будет ругаться
    mutating func moveBy(x deltaX: Int, y deltaY: Int) {
        x += deltaX
        y += deltaY
    }
}

// Обязательно var, иначе опять пиздец
var point = Point(x: 0, y: 0)
point.moveBy(x: 5, y: 5) // Всё, теперь point.x = 5, point.y = 5

А вот как выглядит классический распиздяйский подход, который заставит компилятор материться:

struct Point {
    var x: Int

    // Ошибка компиляции: метод не mutating
    func increment() {
        x += 1 // ❌ Cannot assign to property: 'self' is immutable
        // Типа «сам-то ты кто такой, чтобы меня менять?»
    }
}

let point = Point(x: 0)
point.x = 5 // ❌ Cannot assign to property: 'point' is a 'let' constant
// Ну, тут вообще пиздец, ты её в константу записал, а теперь хочешь поменять? Иди нахуй.

Так что запомни, как отче наш:

  1. Меняешь что-то внутри — вешай mutating на метод. Без вариантов.
  2. Экземпляр структуры делай var. С let только читать можно, писать — нихуя.
  3. Если совсем ебнуться хочется, можно и в геттере mutating сделать, но это уже для извращенцев, которые меняют структуру, когда просто значение читают. Ёперный театр.
  4. А вообще, если данные должны быть святыми и неприкосновенными, лучше создавай новый экземпляр. Мутация — это мощно, но иногда проще отстрелить ногу и вырастить новую, чем лечить старую.