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
}
}
В течение очень долгого времени я был очень озадачен значением изменчивого, модифицируемого. Вот некоторые из моих пониманий, было бы неплохо, если бы вы могли указать на все ошибки, которые могут иметь
Функция мутации в вышеприведенном типе структуры не "мутирует" экземпляр, она заменяет старое значение переменной полностью новым
Мутация означает: действие как функция присваивания, инициализации или мутирования не изменяет текущее значение, но вызывает замену
Значение типизированной переменной класса является неизменным, но вы можете изменить / изменить текущее значение (по этой причине компилятор выдает предупреждение, см. Комментарии с #)
Наблюдатель-установщик может быть вызван только в том случае, если тип является типом значения, потому что установщик сообщает, была ли переменная изменена / заменена (см. Код ниже)
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 ответа
Работа с памятью, как правило, лучше объясняется с помощью изображений, но я попробую здесь:
- Вы вроде как правы, это на самом деле изменяет данные, хранящиеся в месте расположения переменной.
Дана простая структура с мутатором:
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.
Наоборот:) Мутация меняет экземпляр на месте. Вы можете изменить этот экземпляр, скопировав другое значение (как это происходит в
self =
пример), но экземпляр все тот же, только с другим значением.При создании переменной класса вы создаете ссылку на раздел памяти. При установке или изменении этой ссылки
var variableName = classInstance
расположение ссылки остается прежним после инициализации, но местоположение ссылки (если переменная) может измениться.Вы функционально верны, но вам не хватает нюансов. В примере структуры, как указывалось ранее, фактическое значение экземпляра изменяется. В примере класса ссылочная память изменяется, но фактическое значение сохраняется в
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!!