淺談Swift派發(fā)機制
直接派發(fā)
C++ 默認使用的是直接派發(fā),加上 virtual 修飾符可以改成函數表派發(fā)。直接派發(fā)是最快的,原因是調用指令會少,還可以通過編譯器進行比如內聯等方式的優(yōu)化。缺點是由于缺少動態(tài)性而不支持繼承。
struct DragonFirePosition {
var x:Int64
var y:Int32
func land() {}
}
func DragonWillFire(_ position:DragonFirePosition) {
position.land()
}
let position = DragonFirePosition(x: 342, y: 213)
DragonWillFire(position)
編譯 inline 后 DragonWillFire(DragonFirePosition(x: 342, y: 213)) 會直接跳到方法實現的地方,結果就變成 position.land()。
函數表派發(fā)
Java 默認就是使用的函數表派發(fā),通過 final 修飾符改成直接派發(fā)。函數表派發(fā)是有動態(tài)性的,在 Swift 里函數表叫 witness table,大部分語言叫 virtual table。一個類里會用數組來存儲里面的函數指針,override 父類的函數會替代以前的函數,子類添加的函數會被加到這個數組里。舉個例子:
class Fish {
func swim() {}
func eat() {
//normal eat
}
}
class FlyingFish: Fish {
override func eat() {
//flying fish eat
}
func fly() {}
}
編譯器會給 Fish 類和 FlyingFish 類分別創(chuàng)建 witness table。在 Fish 的函數表里有 swim 和 eat 函數,在 FlyingFish 函數表里有父類 Fish 的 swim,覆蓋了父類的 eat 和新增加的函數 fly。
一個函數被調用時會先去讀取對象的函數表,再根據類的地址加上該的函數的偏移量得到函數地址,然后跳到那個地址上去。從編譯后的字節(jié)碼這方面來看就是兩次讀取一次跳轉,比直接派發(fā)還是慢了些。
消息機制派發(fā)
這種機制是在運行時可以改變函數的行為,KVO 和 CoreData 都是這種機制的運用。OC 默認就是使用的消息機制派發(fā),使用 C 來直接派發(fā)獲取高性能。Swift 可以通過 dynamic 修飾來支持消息機制派發(fā)。
當一個消息被派發(fā),運行時就會按照繼承關系向上查找被調用的函數。但是這樣效率不高,所以需要通過緩存來提高效率,這樣查找性能就能和函數派發(fā)差不多了。
具體派發(fā)
聲明
值類型都會采用直接派發(fā)。無論是 class 還是協議 的 extension 也都是直接派發(fā)。class 和協議是函數表派發(fā)。
指定派發(fā)方式
- final:讓類里的函數使用直接派發(fā),這樣該函數將會沒有動態(tài)性,運行時也沒法取到這個函數。
- dynamic:可以讓類里的函數使用消息機制派發(fā),可以讓 extension 里的函數被 override。
派發(fā)優(yōu)化
Swift 會在這上面做優(yōu)化,比如一個函數沒有 override,Swift 就可能會使用直接派發(fā)的方式,所以如果屬性綁定了 KVO 它的 getter 和 setter 方法可能會被優(yōu)化成直接派發(fā)而導致 KVO 的失效,所以記得加上 dynamic 的修飾來保證有效。后面 Swift 應該會在這個優(yōu)化上去做更多的處理。
以上就是淺談Swift派發(fā)機制的詳細內容,更多關于Swift派發(fā)機制的資料請關注腳本之家其它相關文章!
相關文章
Swift?中的?Actors?使用及如何防止數據競爭問題(示例詳解)
Swift中的Actors旨在完全解決數據競爭問題,但重要的是要明白,很可能還是會遇到數據競爭,本文將介紹Actors是如何工作的,以及你如何在你的項目中使用它們,感興趣的朋友跟隨小編一起看看吧2023-06-06
Swift高階函數contains?allSatisfy?reversed?lexicographicallyPr
這篇文章主要為大家介紹了Swift高階函數contains?allSatisfy?reversed?lexicographicallyPrecedes用法示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-06-06

