这里每天分享一个 iOS 的新知识,快来关注我吧
mutating
在 Swift 中,mutating
关键字用于标记结构体和枚举中的方法,允许这些方法修改实例自身或者实例内部的属性。
在默认情况下,在值类型(结构体和枚举)中的方法中是不允许修改属性的。使用 mutating
关键字可以让方法修改属性,从而达到在值类型中修改自身的目的。
swift
struct Point {
var x: Double
var y: Double
func moveBy(x deltaX: Double, y deltaY: Double) {
x += deltaX
y += deltaY
}
}
上边这段代码会报错:

错误提示说的很清楚了,self 是不可变的,如果想让 self 可变,可以在函数名前添加 mutating 关键字。
swift
struct Point {
...
mutating func moveBy(x deltaX: Double, y deltaY: Double) {
x += deltaX
y += deltaY
}
}
当我们为 moveBy
方法使用了 mutating
关键字,将被允许修改 Point
结构体中的属性 x
和 y
。
其实加了这个关键字之后 self 本身也可以修改:
swift
mutating func moveBy(x deltaX: Double, y deltaY: Double) {
self = Self(x: x + deltaX, y: y + deltaY)
}
协议中也可以使用
尽管 mutating
关键字是值类型所独有的,但我们仍然可以将 mutating
函数用在协议上:
swift
protocol GameLife {
var life: Int { get set }
mutating func takeDamage(damage: Int)
}
值类型可以直接使用:
swift
struct Player: GameLife {
var life = 100
mutating func takeDamage(damage: Int) {
life -= damage
}
}
但该协议也可能被用在引用类型,例如类。类在遵守此类协议时需要删除 mutating
关键字,否则编译会报错,因为引用类型本质上是可变的。
kotlin
class Player: GameLife {
var life = 100
func takeDamage(damage: Int) {
life -= damage
}
}
mutating 的实现原理
其实添加 mutating
之后,底层默认传入了一个标记了 inout
的 Self
参数进来,这样 self
就可以修改了,我们尝试修改一下代码,不使用 mutating
关键字来修改值类型属性:
swift
struct Point {
var x = 0.0, y = 0.0
func moveBy(self: inout Self, x deltaX: Double, y deltaY: Double) {
self.x += deltaX
self.y += deltaY
}
}
使用的时候只需要传入 Point
的内存地址:
swift
var somePoint = Point(x: 1.0, y: 1.0)
somePoint.moveBy(self: &somePoint, x: 2.0, y: 3.0)
print("The point is now at (\(somePoint.x), \(somePoint.y))")
// Prints "The point is now at (3.0, 4.0)"
这里每天分享一个 iOS 的新知识,快来关注我吧
本文同步自微信公众号 "iOS新知",每天准时分享一个新知识,这里只是同步,想要及时学到就来关注我吧!