一 异变方法 (mutating关键字)
`struct Point{
var x :Float
var y :Float
mutating func makeAdd (_ x1:Float, _ y1 :Float) {
self.x += x1;
self.y += y1
}
}
var p = Point(x: 10, y: 20)
p.makeAdd(1, 1)`
以上代码执行命令 swiftc main.swift -emit-sil 生成中间代码,可以看到
如果不加mutating关键字,生成 的sil文件是这样的
。
说明@inout 使得Point变得可变。
SIL 文档的解释 An @inout parameter is indirect. The address must be of an initialized object.(当前参数类型是间接的,传递的是已经初始化过的地址)
异变方法的本质:对于变异方法, 传入的 self 被标记为 inout 参数。无论在 mutating 方法内部发生什么,都会影响外部依赖类型的一切。
二 函数调度
class LGTeacher{
func teach(){
print("teach")
} }
extension LGTeacher{
func teach1(){
print("teach1")
}
}
var t = LGTeacher()
t.teach()
t.teach1()
通过sil
可知,类中的方法是通过函数表调用的
可知,extension中的方法通过是直接调用
如果LGTeacher用struct修饰
可知,结构体的方法是是直接派发调用
final关键字 class LGTeacher{
final func teach(){
print("teach") }
} var t = LGTeacher()
t.teach()
vtable中并没有teach方法,通过汇编可知是直接调用。
通过类似的方法可知,@objc关键字和dynamic走的都是函数表查找调用
但是@objc + dynamic走的是消息派发