1.方法排程分類
1.1 方法排程可以分為靜态排程(static dispatch)和動态排程,動态排程從實作上來說又可以劃分為虛拟表也就是Table dispatch比如c++和消息分發message dispatch比如OC用到的就是消息分發機制。
1.2靜态排程和動态排程各有各的好處
1.2.1編譯器可以對靜态排程的方法進行包括inline内聯函數在内的編譯期優化以及加快程式運作速度。
1.2.2動态排程可以實作面向對象程式設計三大特性之一的多态。即在運作時根據調用方去找具體的方法實作。
2.swift中的方法排程
2.1swift中根據方法所定義的位置來講會用到上面所說的三種方法排程方法。
2.1.1 比如struct,enum等值類型中的定義的方法(不包含繼承自某個協定中的方法),定義為final類型的class中的方法以及private方法 ,這些都是靜态排程。
2.1.2 class類型中的方法,protocol中聲明的方法 為table dispatch
2.1.3 nsobject子類中@objc dynamic 方法為message dispatch
3swift中table dispatch的實作
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL4lkaONTRU1ENJpHW4Z0MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLzITO1MTMwITM4AjMxgTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
3.1 如上圖所看到的,class類型的在其中繼資料類型中會引用一個函數指針類型的數組,在對象進行方法調用時去改數組中去查找相對應的方法實作。
3.2 protocol-Witness-Table,Existential Container,value-Witness-Table
3.2.1protocol-Witness-table作用和valuetable一樣,在每一個struct中都會引用這樣一張表,進行相應方法查詢。
3.2.2Existential Container 如上圖所示,由于每一個結構體類型的記憶體大小各不相同,為了保障數組的位元組對齊。使用Existential Container的方式把每個struct對象存入數組中,Existential Container前三個valueBuffer用于存放struct的資料,剩餘兩個分别引用自己的vwt和pwt。需要注意的是如果結構體的屬性過多(big value),那麼會開辟一塊堆區記憶體,然後valuebuffer對這塊記憶體進行引用。為了管理Existential Container 存放的值,是以引用value-Witness-Table建立記憶體,初始化以及記憶體銷毀。
protocol drawable {
func draw()
}
struct point:drawable {
func draw() {
print("draw a point")
}
var x,y:Float;
}
struct line:drawable {
var x1,y1,x2,y2:Float;
func draw() {
print("draw a line")
}
}
var draws = [drawable]()
draws.append(point(x:10,y:10))
draws.append(line(x1: 10, y1: 10, x2: 20, y2: 20))
for temp in draws {
temp.draw()
let size = MemoryLayout<drawable>.size(ofValue: temp)
print("\(type(of: temp))----\(size)") //輸出40
}