1.mutating的使用
2.extension和protocol中的使用
3.mutating的本质
mutating的使用
mutating:(使某物)变化( mutate的现在分词 ); 转变; 突变; 变异.
mutating用于函数的最前面,用于告诉编译器这个方法会改变自身.
swift增强了结构体和枚举的使用,结构体和枚举也可以有构造方法和实例方法,但结构体和枚举是值类型,如果我们要在实例方法中修改当前类型的实例属性的值或当前对象实例的值,必须在func前面添加mutating关键字,表示当前方法将会将会修改它相关联的对象实例的实例属性值.
struct Animal{
var leg:Int
var name:String
init(name:String,leg:Int) {
self.name = name
self.leg = leg
}
//当不声明为mutating时,编译器会提示修复这个错误.
//Cannot assign to property: 'self' is immutable
//Mark method 'mutating' to make 'self' mutable
mutating func changeName(newName:String) {
self.name = newName
}
}
其实我们从编译器的提示信息可以看到端倪,不能够对这个属性赋值,因为self是不可以变的(值类型),标记这个方法为mutating使self变为可变的(inout).
protocol和extension中的使用
//定义一个协议
protocol Toggleable {
mutating func toggle()
}
//枚举
enum lightbulb:Toggleable{
case on
case off
mutating func toggle(){
switch self {
case .on:
self = .off
case .off:
self = .on
}
}
}
//类无需标明 引用类型
class TableLamp: Toggleable {
var isOn:Bool = false
func toggle() {
isOn = !isOn
}
}
//在扩展中使用
extension lightbulb{
mutating func newToggle(isOn:Bool){
if isOn {
self = .on
}else{
self = .off
}
}
}
协议中,当在结构体或者枚举实现协议方法时,若对自身属性作修改,需要将协议的方法声明为mutating,对类无影响.
在扩展中,同样若对自身属性作修改,需要将方法声明为mutating
mutating的本质
当我们option点击查看mutating的方法,可以看到
var dog = Animal(name: "erha", leg: 4)
//点击option查看结果 let funcs: (inout Animal) -> (String) -> ()
let funcs = Animal.changeName
//传入需要改变的变量.得到返回的闭包
let returnClourse = funcs(&dog)
//调用返回的闭包
returnClourse("Sam")
print(dog.name)//Sam
实际上是一个接受参数为self,返回一个函数的函数,以inout的方式传入自身,inout能够让函数修改传递过来的参数,并且在函数调用结束后将参数所做的改动保留下来.
结论:mutating方法的第一个参数是self,并且以inout的方式传入,因为值类型在参数传递的时候会被复制,所以对于非mutating方法,self其实是值的副本,为了进行修改,self需要被声明为inout,而mutating的本质就是编译器帮我们完成的这个任务.