讓我們直接來到三部曲的終章,為了營造終局的高潮我塞了不少資訊在這篇文章裡,大家先喝點水伸展一下。
前篇提到了一個破天荒的想法,自己實做一個 Protocol Witness Table,所以我們先來深入點看看 Protocol Witness Table,首先是 compiler 在 SIL 階段做了什麼事(官方文件),首先文件裡提到
A witness table is emitted for every declared explicit conformance.
所以每當我們當聲明一個型別遵守(confrom to)某個 Protocol 時就會生成一個 witness table,而這個 witness table 會用「型別:Protocol」這組合生成一個獨特的 id 來當 key 保存著,文件裡共定義五種遵守 protocol 的可能性,我們只看最一般的一般性遵守
protocol-conformance ::= normal-protocol-conformance
因為每個型別只能遵守一個 protocol 一次(重點重點!),所以可以保證這樣的配對是 1:1,而且也只有這個一般的遵守方式會直接與 witness table 關聯,其它比較複雜的情況多半是間接或多個 table 之間的關聯。至於一個 witness table 會由 4 個 entry 組成以描述所有相關資訊,我們只在意最重要的一個 method entry:
sil-witness-entry ::= 'method' sil-decl-ref ':' sil-function-name
這裡很單純,前者是 protocol 所定義的介面,後者是真實的 method 實作,只是把它們連結起來而已,如這裡太抽象我們可以看一下圖和程式碼,就拿 WWDC 2016 Session 416 的範例來說:
我們這裡的變數 point 會是個 Existential Container,因為我們宣告它的型別是個 protocol,結合前述所說,container 和 protocol witness table 長得像這樣(大家還記得第二集講到 container 的模樣嗎?)