0

让我们从一些代码段开始

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. 上述结构类型中的变异函数不会“变异”实例,它会将变量的旧值替换为全新的值

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

  3. 类类型变量的值是不可变的,但您可以修改/更改当前值(这是编译器发出警告的原因,请参阅带 # 的注释)

  4. setter 观察者,只能在类型是值类型时调用,因为 setter 告诉变量是否已被变异/替换(请参见下面的代码)

    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
    

感谢您的时间和帮助

4

2 回答 2

2

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

  1. 你说得对,它实际上是在改变存储在变量位置的数据。

给定一个带有 mutator 的简单结构:

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

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

于 2017-03-01T18:16:50.410 回答
0

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

    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!!
于 2017-03-01T18:39:20.153 回答