Mutable和Modifialbe是什么意思?

时间:2017-03-01 17:30:59

标签: swift types mutable property-observer mutating-function

让我们从一些代码段开始

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

  5. 只有在类型为值类型时才能调用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
    
  6. 感谢您的时间和帮助

2 个答案:

答案 0 :(得分:1)

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

  1. 你是对的,它实际上是在改变存储在变量位置的数据。
  2. 给出一个带有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. 相反:) Mutating就地更改实例。您可以通过复制不同的值来更改该实例(如self =示例中所示),但实例仍然是相同的实例,只是具有不同的值。

    2. 创建类变量时,您正在为内存部分创建引用。设置或更改引用var variableName = classInstance时,引用的位置在初始化后保持不变,但引用的位置(如果var)可以更改。

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

答案 1 :(得分: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!!