1、關(guān)鍵字mutating
通過(guò)SIL對(duì)比一下添加mutating和不添加的兩者區(qū)別
struct Point {
var x = 0.0, y = 0.0
func test(){
let tmp = self.x
}
mutating func moveBy(x deltaX: Double, y deltaY: Double) {
x += deltaX
y += deltaY
}
}
Xcode配置執(zhí)行腳本命令
swiftc -emit-sil ${SRCROOT}/LGSwiftTest/main.swift > ./main.sil
打開(kāi)main.sil文件
// func test
sil hidden @$s4main5PointV4testyyF : $@convention(method) (Point) -> ()
debug_value %0 : $Point, let, name "self", argno 1, implicit // id: %1
// func moveBy
sil hidden @$s4main5PointV6moveBy1x1yySd_SdtF : $@convention(method) (Double, Double, @inout Point) -> ()
SIL 文檔的解釋
An @inout parameter is indirect. The address must be of an initialized object.(當(dāng)前參數(shù) 類(lèi)型是間接的,傳遞的是已經(jīng)初始化過(guò)的地址)
總結(jié):
異變方法的本質(zhì):對(duì)于變異方法, 傳入的 self 被標(biāo)記為 inout 參數(shù)。無(wú)論在 mutating 方法 內(nèi)部發(fā)生什么,都會(huì)影響外部依賴類(lèi)型的一切。
輸入輸出參數(shù):如果我們想函數(shù)能夠修改一個(gè)形式參數(shù)的值,而且希望這些改變?cè)诤瘮?shù)結(jié)束之后 依然生效,那么就需要將形式參數(shù)定義為 輸入輸出形式參數(shù) 。在形式參數(shù)定義開(kāi)始的時(shí)候在前邊 添加一個(gè) inout關(guān)鍵字可以定義一個(gè)輸入輸出形式參數(shù)
2、函數(shù)調(diào)用
2.1、函數(shù)調(diào)用
1、函數(shù)的地址空間是連續(xù)的。
看一下如下函數(shù)調(diào)用
class LGTeacher{ //繼承關(guān)系嗎?沒(méi)有
//消息調(diào)度的機(jī)制
func teach(){
print("teach")
}
func teach1(){
print("teach1")
}
func teach2(){
print("teach2")
}
}
let t = LGTeacher()
t.teach()
t.teach1()
t.teach2()
從上述匯編和si可以看出,函數(shù)的地址空間是連續(xù)的,teach函數(shù)的調(diào)用過(guò)程:找到 Metadata 基于函數(shù)表的調(diào)度確定函數(shù)地址(metadata + 偏移量), 執(zhí)行函數(shù),函數(shù)存放的位置為vtable中。
2.2、@_dynamicReplacement 方法替換
class LGTeacher {
dynamic func teach(){
print("teach")
}
}
extension LGTeacher {
@_dynamicReplacement(for: teach)
func teach3() {
print("tech3333")
}
}
編譯后的sil
文件
// LGTeacher.teach3()
sil hidden [dynamic_replacement_for "$s14ViewController9LGTeacherC5teachyyF"] [ossa] @$s14ViewController9LGTeacherC6teach3yyF : $@convention(method)
最終方法teach3()
被替換為teach()