在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
}
}
错误的消息竟然是 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 的实现是完全透明,可以当作不存在的。
网友评论