斯威夫特3
(我已經在你的榜樣取代IndexableBase
與Collection
,你應該更喜歡後者)
按照Swift 3,協議組合使用infix ope rator &
較protocol<...>
構建體,如在接受和執行進化提案描述:
因此,使用協議的組合物也可放置組合式約束在該參數的T
佔位符清單:
class MyCustomClass<T: Equatable & Collection> { /* ... */ }
作爲協議組合的替代方案,您還可以使用where
子句來加入多個類型(和子類型)約束。按接受和實施發展建議:
的where
條款已被轉移到聲明的結束,在這種情況下,你的例子將是:
class MyCustomClass<T: Equatable> where T: Comparable { /* ... */ }
或,甚至將完整的協議組合與where
子句放在聲明末尾
class MyCustomClass<T> where T: Equatable & Comparable { /* ... */ }
我們應該喜歡什麼風格?
有趣的討論是我們應該考慮的「最佳實踐」,因爲這個特定的主題沒有指定Swift API指南。難道我們把
- 所有(主要類型)約束的參數列表,或
- 在聲明的末尾的所有限制,或
- 分手約束與一些參數列表和其他人置於宣言結束?
考慮以下人爲的例子,其中我們有一個構建體,我們打算作爲一種類型的約束(Doable
),這本身持有associatedtype
這是我們可以將一種類型的約束使用的協議。
protocol Doable {
associatedtype U
}
使用上面的方法不同,下面所有的三種方法是有效的,語法
// alternative #1
func foo<T: Equatable & Doable>(_ bar: T) ->() where T.U: Comparable { /* ... */ }
// alternative #2
func foo<T: Equatable>(_ bar: T) ->() where T: Doable, T.U: Comparable { /* ... */ }
// alternative #3
func foo<T>(_ bar: T) ->() where T: Equatable & Doable, T.U: Comparable { /* ... */ }
我會從the evolution thread that that brought forth SE-0081引述蘋果開發喬格勒夫:
這是一個主觀判斷。這是我的感覺是,在很多情況下,一個通用的 參數是由至少一個重要的協議或基地 類是值得呼叫前面,所以這是合理的,允許像
func foo<C: Collection>(x: C) -> C.Element
萬物而不放逐Collection
約束這個限制距離聲明的前面 太遠了。
因此在上面的人爲的例子,它可能是適當的在參數列表中使用的協議的組合物爲直接適用於通用的佔位符T
類型的限制,並把這些約束,而的T.U
亞型約束是放置在聲明的最後。即,上面的替代方案#1。
Where運算符適合我(Xcode 8.1,Swift 3),所以我使用這個解決方案。 – altralaser
@altralaser即使這個在你的Swift 3中「起作用」,它應該給你一個警告,即[** emphasis ** mine]:_「warning:'where''子句旁邊的通用參數**已被棄用並且將在未來版本的Swift **「_」中被刪除。因此,您可能希望使用Swift 3的最新解決方案,否則您的實現將在Swift的未來更新中被破解(請參閱Swift 3最新版本的其他兩個答案)。 – dfri