# mutating getter / nonmutating setter

在預設的情況下，**getter** 是 **nonmutating**，而 **setter** 是 **mutating**。

但如果 **getter** 內部的程式碼**變更了物件的屬性**，則這個 getter 必須標註 **mutating**。

反過來說，如果 **setter** 內部的程式碼**沒有變更物件的屬性**，那麼這個 setter 就可以標註為 **nonmutating**，當標註為 nonmutating 之後，就算是一個 **let** 變數，也可以用這個 setter。

{% tabs %}
{% tab title="Mutating Getter" %}

```swift
/*
 Mutating Getter & Nonmutating Setter
 https://gist.github.com/hanawat/26f64afba4e6461dc27c
 */

// Mutating Getter
struct Reference {
    
    private let _value: Double  // inner value of this instance
    var          count = 0      // times this inner value has been referenced.
    
    init(value: Double) { _value = value }
    
    var value: Double { 
        mutating get {        // ⭐️ mutating getter
            count += 1        //    mutates `count` property
            return _value
        }
    }
}

var ref = Reference(value: 0.125)
for _ in 0..<5 { print(ref.value) } // reference its value 5 times.
print(ref.count)                    // 5
```

{% endtab %}

{% tab title="Nonmutating Setter" %}

```swift
// Nonmutating Setter
struct Independent {
    
    private static var _pool = [Double]() // pool of values for this type
    let index: Int                        // instance index
    
    init(value: Double) {
        index = Independent._pool.count
        Independent._pool.append(value)
    }
    
    // instance method
    var value: Double {
        
        // ⭐️ 注意：
        //    這個物件的設計從來沒有把 _pool 裡面的東西刪除，
        //    否則這裡的 _pool[index] 可能會出問題。
        get { return Independent._pool[index] }
        
        // ⭐️ nonmutating setter
        //    instance property `index` is NOT mutated.
        //    only TYPE property `_pool` is mutated.
        nonmutating set { Independent._pool[index] = newValue }
    }
    
    // ⭐️ type method
    static func clear() {
        _pool = _pool.flatMap { _ in 0.0 }
    }
}

// ⭐️ this is a `let`
let a0 = Independent(value: 0.125)

print(a0.value)      // 0.125
a0.value = 5.25      // ⭐️ but its value can be changed.
print(a0.value)      // 5.25

Independent.clear()
print(a0.value)      // 0.0
```

{% endtab %}

{% tab title="📗 參考" %}

* [Mutating Getter](https://gist.github.com/hanawat/26f64afba4e6461dc27c) - GitHub Gist
* [The Inner Workings of State Properties of SwiftUI](https://t.co/v4vfJ88vPK?amp=1) - Medium
  {% endtab %}

{% tab title="👥 相關" %}

* [state](https://lochiwei.gitbook.io/ios/swiftui/view/state/value/state "mention") - ?
  {% endtab %}
  {% endtabs %}
