斯威夫特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