基于本文回答

播面 播面

刷题像听歌,多听自然懂
0
评论

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 在底层做了两件事:

  1. 隐式的 self 变为 inout 参数
    普通方法的 self 是值传递(常量),而 mutating 方法的 self 是通过引用传递(inout)。
  2. 写回机制
    方法执行时,你可以修改 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,因为类是引用类型,其方法默认就可以修改属性。
00:00
00:00