上次寫完 PAT (Protcol with Assocaited Type) 不能做為型別的另一種解法沒多久(請見重新檢視 Swift 的 Protocl(二)),就迎來 WWDC 2019,在萬眾矚目的 SwiftUI 裡立刻展現了官方解決這個問題的帥氣手法,some View,也適逢 Podcast 提問箱有人提問什麼是 Opaque Result Type ,本期 Podcast 只有點到沒有深聊,所以在這討論一下。
為何要有 Opaque Result Type
首先了解一下這個特性要解決什麼 Swift 5.1 前無法解決的問題:
型別上對返回類型的抽象化無法被實現 (Type-level abastraction of returns)
無法建立帶有泛型類型的 existentail container (也就是無法用 PAT 做為一種類型)
如果有巢狀結構或是那種多層的泛型使用時常會需要在宣告時指明多層又臭又長的各層類型,像是:
可見最後 EightPointedStar.shape 的定義是多麼地可怕,以上幾個問題其實都來自於一個原先 Swift 泛型系綂設計的不足,那就是:
只能由呼叫方(caller)來決定被呼叫方(callee)泛型參數最終要填入的真正型別
我們回顧一下實例:
所以 Opaque Result Type 最重要的精神就是讓被呼叫方(callee),也就是實作方決定要回什麼真實的型別;因此外部呼叫後得到的就會是一個抽象的型別,這點與先前在宣告時給參數,外部需要明確地給予一個決定性的真實型別相反,可以視作是反向的泛型(reverse-generic)。
有了這個特性,我們前面的 EightPointedStar 就可以簡化成
至於 PAT,我們就拿 SwiftUI 裡的 some View 來說明,基本上 View 是一個帶有 associated type 的 Protocol