swift mutating关键字

在Swift中,包含三种类型struct, enum, class

其中struct和enum是值类型, class是引用类型,但是与Objective-C不同的是,structureenumeration也可以拥有方法(method),其中方法可以为实例方法,也可以为类方法,实例方法是和类型的一个实例绑定的。

mutating 用法

一、Struct Mutable 的⽅法

在 Swfit 中我们基本都是⽤ struct 去定义⼀个纯数据类型。⽐如

struct User {
  var age : Int
  var weight : Int
  var height : Int
}

⽽有我们经常会在变量⾥添加⼀些简单的改变变量⾥内容的⽅法,⽐如

func gainWeight(newWeight: Int) {
  weight += newWeight
}

但如果我们直接把这个⽅法放⼊ User 这个变量中间,你的编译器就会给出⼀个⾮常奇怪的错误消息

struct User {
  var age : Int
  var weight : Int
  var height : Int
  func gainWeight(newWeight: Int) {
    weight += newWeight
  }
}
swift mutating关键字_第1张图片

错误的消息竟然是 Binary operator '+=' cannot be applied to two int operands ,意思是在2个数字之间没有办法使⽤ += 。但⼤家都知道 += 在数字变量之间是最常⻅不过的,为什么不能⽤?

其实在这个错误代码后⾯有另⼀层意思。因为我们忽略了⼀点,Struct 出来的变量是 Immutable的,想要⽤⼀个⽅法去改变变量⾥⾯的值的时候必须要加上⼀个关键词 mutating ,所以其实这个错误代码的真正含义应该是 因为 User 的 Weight 是 Immutable 的,所以+= ⽆法在这两个 Int 上使⽤我们在⽅法之前加上 mutating 之后编译就可以顺利进⾏了

struct User {
  var age : Int
  var weight : Int
  var height : Int
  mutating func gainWeight(newWeight: Int) {
    weight += newWeight
  }
}

二、将protocol 的⽅法声明为 mutating

Swift 的 protocol 不仅可以被 class 类型实现,也适⽤于 struct 和 enum 。因为这个原因,我们在写给别⼈⽤的接⼝时需要多考虑是否使⽤ mutating 来修饰⽅法,⽐如定义为 mutating func myMethod() 。Swift 的 mutating 关键字修饰⽅法是为了能在该⽅法中修改 struct 或是 enum 的变量,所以如果你没在接⼝⽅法⾥写 mutating 的话,别⼈如果⽤ struct 或者 enum 来实现这个接⼝的话,就不能在⽅法⾥改变⾃⼰的变量了。⽐如下⾯的代码

protocol Vehicle {
    var numberOfWheels: Int {get}
    var color: UIColor {get set}
    
    mutating func changeColor()
}

struct Car: Vehicle {
    let numberOfWheels = 4
    var color = UIColor.blue
    
    mutating func changeColor() {
        color = UIColor.red
    }
}

如果把 protocol 定义中的 mutating 去掉的话, Car 就怎么都过不了编译了:保持现有代码不变的话,会报错说没有实现接⼝;如果去掉 mutating 的话,会报错说不能改变结构体成员。这个接⼝的使⽤者的忧伤的眼神,相信你能想象得出。另外,在使⽤ class 来实现带有 mutating 的⽅法的接⼝时,具体实现的前⾯是不需要加mutating 修饰的,因为 class 可以随意更改⾃⼰的成员变量。所以说在接⼝⾥⽤ mutating 修饰⽅法,对于 class 的实现是完全透明,可以当作不存在的。

你可能感兴趣的:(swift mutating关键字)