异变方法
Swift 中 class 和 struct 都能定义方法。但是有一点区别的是默认情况 下,值类型属性不能被自身的实例方法修改。
struct Point {
var x = 0.0, y = 0.0
// 编译时会报错
func moveBy(x deltaX: Double, y deltaY: Double) {
//self
self.x += deltaX
self.y += deltaY
}
}
moveBy由于修改了自身,所以会编译不通过 需要在前面加mutating
struct Point {
var x = 0.0, y = 0.0
mutating func moveBy(x deltaX: Double, y deltaY: Double) {
self.x += deltaX
self.y += deltaY
}
}
异变方法的本质:对于变异方法, 传入的 self 被标记为 inout 参数。无论在 mutating 方法 内部发生什么,都会影响外部依赖类型的一切
在结构体中:函数默认self是以值类型传入,加了mutating之后self是指针的方式传入
方法的调度
- OC:使用objc_msgSend
- swift:找到Metadata,确定函数地址(Metadata + 偏移量),执行函数,基于函数表的调度
方法调度方式
类型 调度方式 extension
值类型 静态派发 静态派发
类 函数表派发 静态派发
NSObject子类 函数表派发 静态派发
静态派发:直调调用函数地址
影响函数派发方式
- final:添加了final关键字的函数无法被重写,使用静态派发,不会再v-table中出现,且对objc运行时不可见
- dynamic:函数均可添加dynamic关键字,为非objc类和值类型函数赋予动态性,但派发方式还是函数表派发
- @objc:该关键字可以将Swift函数暴露给objc运行时,依旧是函数表派发
- @objc + dynamic:消息派发方式(OC消息传递)
在原swift中是没有runtime的,除非加了@objc