Mutable 和 Modifialbe 它们的含义是什么?

Mutable and Modifialbe what is the meaning of them?

让我们从一些代码段开始

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
    }
}

很长一段时间,我对mutable、modifiable的含义很困惑。以上是我目前的一些理解,如果能指出其中可能存在的错误就更好了

  1. 上述结构类型中的变异函数没有"mutates"实例,它将用一个全新的值替换变量的旧值

  2. 变异意味着:赋值、初始化或变异函数等动作不会修改当前值,但会触发替换

  3. 一个 class 类型变量的值是不可变的,但你可以 modify/change 当前值(这是编译器发出警告的原因,请参阅注释#)

  4. setter观察者,只能在类型为值类型时调用,因为setter告诉变量是否已经mutated/replaced(请看下面的代码)

    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
    

感谢您的宝贵时间和帮助

使用图像可以更好地解释内存处理,但我会在这里试一试:

  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 仍将驻留在相同的内存位置,但您正在手动创建 Example 的全新实例,然后将该实例中的数据复制到 mutableExample。

  1. 相反 :) 变异就地改变了实例。您可以通过复制不同的值来更改该实例(如 self = 示例中所发生的那样),但该实例仍然是同一个实例,只是具有不同的值。

  2. 创建 class 变量时,您正在创建对一段内存的 引用。设置或更改该引用 var variableName = classInstance 时,引用的位置在初始化后保持不变,但被引用的位置(如果是 var)随后可以更改。

  3. 您在功能上是正确的,但缺少一些细微差别。在结构示例中,如前所述,实例的实际值正​​在发生变化。在 class 示例中,引用的内存在变化,但存储在 b 中的实际值没有变化。

观察者观察值的变化,class类型变量的值是指向对象的引用。要触发 属性 观察器,必须更改引用。

    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!!