Swift mutating 关键字的作用
在 Swift 中,mutating 关键字主要用于 结构体 (Struct) 和 枚举 (Enum) 这类值类型 (Value Types)。
简单来说,它的作用是:允许在值类型的方法中修改该实例本身的属性,或者替换该实例本身。
以下是详细的解释:
1. 为什么需要 mutating?
在 Swift 中,结构体和枚举是值类型。默认情况下,值类型的实例方法是不允许修改其属性的。
即使你的属性定义为 var(变量),在实例方法内部,self(即实例本身)被隐式地视为一个常量 (let)。因此,你无法修改它持有的任何属性。
如果你尝试修改,编译器会报错:
"Cannot assign to property: 'self' is immutable"
2. 如何使用
为了让方法能够修改属性,你需要在 func 关键字前面加上 mutating。
示例:结构体 (Struct)
错误写法:
plaintext
struct Point {
var x = 0.0
var y = 0.0
// 报错!默认情况下不能在方法内修改 x 和 y
func moveBy(x deltaX: Double, y deltaY: Double) {
x += deltaX
y += deltaY
}
}
正确写法 (使用 mutating):
plaintext
struct Point {
var x = 0.0
var y = 0.0
// 加上 mutating 关键字
mutating func moveBy(x deltaX: Double, y deltaY: Double) {
x += deltaX
y += deltaY
}
}
var fixedPoint = Point(x: 1.0, y: 1.0)
fixedPoint.moveBy(x: 2.0, y: 3.0) // x 变成 3.0, y 变成 4.0
示例:枚举 (Enum)
枚举也可以包含方法,并且可以使用 mutating 来切换自身的状态(即改变 self)。
plaintext
enum SwitchState {
case off, on
mutating func next() {
switch self {
case .off:
self = .on // 直接修改 self
case .on:
self = .off
}
}
}
var light = SwitchState.off
light.next() // light 变成了 .on
3. mutating 的底层原理
当你把一个方法标记为 mutating 时,Swift 在底层做了两件事:
- 隐式的
self变为inout参数:
普通方法的self是值传递(常量),而mutating方法的self是通过引用传递(inout)。 - 写回机制:
方法执行时,你可以修改self。方法执行结束后,修改后的结构体会被写回到原来的变量中。
这也解释了为什么你不能在一个 let 定义的结构体常量上调用 mutating 方法:
plaintext
let fixedPoint = Point(x: 1.0, y: 1.0)
// 报错!因为 fixedPoint 是常量,无法被“写回”修改
fixedPoint.moveBy(x: 2.0, y: 3.0)
4. 协议 (Protocol) 中的 mutating
如果你定义了一个协议,并且希望采纳该协议的类型能够修改自身状态,你需要将协议方法声明为 mutating。
plaintext
protocol Toggleable {
mutating func toggle()
}
- 结构体/枚举实现时:必须加上
mutating关键字。 - 类 (Class) 实现时:不需要加
mutating关键字(因为类是引用类型,方法本来就可以修改属性)。
总结
- 适用对象:结构体 (Struct)、枚举 (Enum)。
- 核心作用:允许方法修改实例的属性或赋值给
self。 - 类 (Class):不需要使用
mutating,因为类是引用类型,其方法默认就可以修改属性。