Mutable и Modifialbe в чем их смысл?

Давайте начнем с некоторых сегментов кода

struct DigitS {
    var number = 42
    init(_ n: Int) {
        self.number = n
    }
    mutating func replace() {
        self = DigitS(12) // mutating 
    }
}

class DigitC {
    var number = 42
    init(_ n: Int) {
        self.number = n
    }
    func replace() {
        self = DigitC(12) //#Cannot assign to value: "self" is immutable
    }
}

В течение очень долгого времени я был очень озадачен значением изменчивого, модифицируемого. Вот некоторые из моих пониманий, было бы неплохо, если бы вы могли указать на все ошибки, которые могут иметь

  1. Функция мутации в вышеприведенном типе структуры не "мутирует" экземпляр, она заменяет старое значение переменной полностью новым

  2. Мутация означает: действие как функция присваивания, инициализации или мутирования не изменяет текущее значение, но вызывает замену

  3. Значение типизированной переменной класса является неизменным, но вы можете изменить / изменить текущее значение (по этой причине компилятор выдает предупреждение, см. Комментарии с #)

  4. Наблюдатель-установщик может быть вызван только в том случае, если тип является типом значения, потому что установщик сообщает, была ли переменная изменена / заменена (см. Код ниже)

    struct Digit {
        var number = 12
    }   
    var b = Digit() {
        didSet{ print("number is set") }
    }  
    b.number = 22 // observer is called
    
    
    
    class Digit {
         var number = 12
        }   
    var b = Digit() {
         didSet{ print("number is set") }
        }
    
    b.number = 22 // observer is not called
    

Спасибо за ваше время и помощь

2 ответа

Решение

Работа с памятью, как правило, лучше объясняется с помощью изображений, но я попробую здесь:

  1. Вы вроде как правы, это на самом деле изменяет данные, хранящиеся в месте расположения переменной.

Дана простая структура с мутатором:

struct Example {
    var text: String

    mutating func changeText(to newText: String) {
        self.text = newText
    }
}

let constantExample = Example(text: "Test") //Makes a section of memory that isn't allowed to change.
constantExample.changeText(to: "Other Test") //This doesn't work because constantExample isn't mutable.

var mutableExample = Example(text: "Test") //Makes a section of memory that is allowed to change.
mutableExample.changeText(to: "Other Test") //This doesn't make a new copy, but rather changes the value in mutableExample's section of memory

Если бы вы использовали конкретный случай, который вы упомянули:

mutating func changeText(to newText: String) {
    self = Example(text: "A new text")
}

mutableExample будет по-прежнему находиться в той же области памяти, но вы вручную создаете совершенно новый экземпляр примера и затем копируете эти данные из этого экземпляра в mutableExample.

  1. Наоборот:) Мутация меняет экземпляр на месте. Вы можете изменить этот экземпляр, скопировав другое значение (как это происходит в self = пример), но экземпляр все тот же, только с другим значением.

  2. При создании переменной класса вы создаете ссылку на раздел памяти. При установке или изменении этой ссылки var variableName = classInstance расположение ссылки остается прежним после инициализации, но местоположение ссылки (если переменная) может измениться.

  3. Вы функционально верны, но вам не хватает нюансов. В примере структуры, как указывалось ранее, фактическое значение экземпляра изменяется. В примере класса ссылочная память изменяется, но фактическое значение сохраняется в b не меняется.

Наблюдатель наблюдает за изменением значения, значение типизированной переменной класса - это контрольные точки объекта. Чтобы вызвать наблюдателя свойства, необходимо изменить ссылку.

    class Digit {
        var number = 12
    }

    var a = Digit()

    var b = Digit() {
        didSet{ print("number is set") }
    }

    b.number = 22 // observer is called

    b = a //observer is called here!!
Другие вопросы по тегам