Ответ
Свойства структуры можно изменять, но с важным ограничением: методы, изменяющие свойства, должны быть помечены как 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
Практические рекомендации:
- Используйте
mutatingдля методов, изменяющих любые свойства - Структура должна быть объявлена как
var, а неlet - Для вычисляемых свойств используйте
mutating getесли свойство изменяет self - Рассмотрите создание новой структуры вместо мутации для иммутабельных данных
Ответ 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
// Ну, тут вообще пиздец, ты её в константу записал, а теперь хочешь поменять? Иди нахуй.
Так что запомни, как отче наш:
- Меняешь что-то внутри — вешай
mutatingна метод. Без вариантов. - Экземпляр структуры делай
var. Сletтолько читать можно, писать — нихуя. - Если совсем ебнуться хочется, можно и в геттере
mutatingсделать, но это уже для извращенцев, которые меняют структуру, когда просто значение читают. Ёперный театр. - А вообще, если данные должны быть святыми и неприкосновенными, лучше создавай новый экземпляр. Мутация — это мощно, но иногда проще отстрелить ногу и вырастить новую, чем лечить старую.