在 Swift 中,结构体 (struct) 默认是值类型:当复制结构体的实例时,会创建一个独立的副本。然而,与类不同,结构体的方法在没有编译器的直接许可时不能修改 self 及其属性。在早期版本的 C 和 C++ 中,结构体总是可变的,这导致了意想不到的副作用。Swift 提高了安全性,要求显式标记那些修改结构体状态的方法,使用关键字 mutating。
如果一个方法需要修改结构体的属性,但声明为普通方法,编译器将不允许这样做,这就是问题所在。如果没有 mutating,就无法更改 self 或其属性。
解决方案是使用关键字 mutating 来声明这样的函数,这向编译器发出信号,允许修改 self 及其嵌套属性。
代码示例:
struct Counter { var value = 0 mutating func increment() { value += 1 } // 如果去掉 mutating,这个方法将无法编译 } var counter = Counter() counter.increment() // value 变为 1
关键特性:
1. 可以在通过 let 声明的结构体上调用 mutating 方法吗?
不,可以。在 let 常量的结构体上不能进行修改,即使使用了 mutating 方法。
let counter = Counter() counter.increment() // 编译错误
2. 结构体内的类的嵌套属性可以在结构体的 mutating 方法内修改吗?
可以,如果结构体的属性是引用类型 (例如类),则可以在没有 mutating 的情况下修改它的内部属性,但要修改整个结构体只能通过 mutating。
class State { var value = 0 } struct Wrapper { var state = State() mutating func change() { state.value += 1 } }
3. 在没有 mutating 的情况下能否仅在方法中修改计算属性?
不可以。如果计算属性有 set,那么在方法内部修改其值仍然需要 mutating。
在项目中实现了一个简单的计数器结构,但开发人员忘记将该方法标记为 mutating。测试未通过,因为值未改变。
优点:
缺点:
结构体中的方法标记为 mutating,测试通过,修改正确更新。代码对团队所有成员都清晰。
优点:
缺点: