4種派發(fā)機制:
1看锉、內(nèi)聯(lián)(inline)最快
2、靜態(tài)派發(fā)(Static Dispatch)
3斗蒋、函數(shù)表派發(fā)(Virtual Dispatch)
4煤惩、動態(tài)派發(fā)(Dynamic Dispatch)(最慢)
Swift 的派發(fā)方式總結(jié):
- 值類型 : 靜態(tài)派發(fā)
- final、擴展 :靜態(tài)派發(fā)
- 引用類型:函數(shù)表派發(fā)
- 協(xié)議 :函數(shù)表派發(fā)(單獨的函數(shù)表派發(fā))
- dynomic + @objc :走消息機制
dynamic 關鍵字可以用于修飾變量或函數(shù)猾浦,它的意思也與 Objective-C 完全不同陆错。它告訴編譯器使用動態(tài)分發(fā)而不是靜態(tài)分發(fā)灯抛。Objective-C 區(qū)別于其他語言的一個特點在于它的動態(tài)性,任何方法調(diào)用實際上都是消息分發(fā)音瓷,而 Swift 則盡可能做到靜態(tài)分發(fā)对嚼。
因此,標記為 dynamic 的變量或函數(shù)會隱式的加上 @objc 關鍵字绳慎,他會使用 Objective-C 的 runtime 機制纵竖。
@objc 修飾符:可以將 Swift 類型文件中的類、屬性和方法等偷线,暴露給Objective-C 類使用
swift中函數(shù)派發(fā)查看方式:可將swift代碼轉(zhuǎn)換為SIL(中間碼)
swiftc -emit-silgen -O example.swift
如何在Swift中使用動態(tài)派發(fā)和靜態(tài)派發(fā)磨确?
- 動態(tài)派發(fā)
- 可以使用繼承,重寫父類的方法 -> 函數(shù)表派發(fā)
- 使用dynamic + @objc声邦,方法公開給OC runtime使用 -> 消息機制
在這種類型的派發(fā)中乏奥,在運行時而不是編譯時選擇實現(xiàn)方法亥曹,會增加運行時的性能開銷邓了。
優(yōu)勢:具有靈活性(大多數(shù)的OOP語言都支持動態(tài)派發(fā),因為它允許多態(tài))
- 靜態(tài)派發(fā)
- final 關鍵字
- static 關鍵字
優(yōu)勢:和動態(tài)派發(fā)相比媳瞪,非称快。編譯器可以在編譯器定位到函數(shù)的位置蛇受。因此函數(shù)被調(diào)用時句葵,編譯器能通過函數(shù)的內(nèi)存地址,直接找到它的函數(shù)實現(xiàn)兢仰。極大的提高了性能乍丈,可以達到類型inline的編譯期優(yōu)化
動態(tài)派發(fā)有兩種形式:
- 函數(shù)表派發(fā)(Table Dispatch)
這種調(diào)用方式利用一個表,該表是一組函數(shù)指針把将,稱為witness table轻专,以查找特定方法的實現(xiàn)
- witness table如何工作?
每個子類都有它自己的表結(jié)構(gòu)
對于類中每個重寫的方法察蹲,都有不同的函數(shù)指針
當子類添加新方法時请垛,這些方法指針會添加在表數(shù)組的末尾
最后,編譯器在運行時使用此表來查找調(diào)用函數(shù)的實現(xiàn)
由于編譯器必須從表中讀取方法實現(xiàn)的內(nèi)存地址洽议,然后跳轉(zhuǎn)到該地址宗收,一次它需兩條附加指令,因此它比靜態(tài)派發(fā)慢亚兄,但仍比消息派發(fā)快
- 消息派發(fā)(Message Dispatch)
這種動態(tài)派發(fā)方式是最動態(tài)的混稽。事實上它表現(xiàn)優(yōu)異,目前Cocoa框架在KVO,CoreData等很多地方在使用它
此外荚坞,它還可以使用method swizzling,可以在運行時更改函數(shù)的實現(xiàn)菲盾。
Swift本身不支持消息派發(fā)颓影,而是利用OC的runtime特性,間接實現(xiàn)這種動態(tài)性懒鉴。
要使用動態(tài)性需要使用dynamic關鍵字诡挂。Swift4.0之前,需要一起使用dynamic和@objc临谱。Swift4.0之后璃俗,只需表明@objc讓方法支持oc的調(diào)用,以支持消息派發(fā)
參考鏈接:http://www.reibang.com/p/6a0929424ac1
https://blog.csdn.net/LiqunZhang/article/details/115175965