Swift中的多个types约束
比方说,我有这些协议:
protocol SomeProtocol { } protocol SomeOtherProtocol { }
现在,如果我想要一个采用genericstypes的函数,但该types必须符合SomeProtocol
我可以这样做:
func someFunc<T: SomeProtocol>(arg: T) { // do stuff }
但有没有办法为多个协议添加types约束?
func bothFunc<T: SomeProtocol | SomeOtherProtocol>(arg: T) { }
类似的东西使用逗号,但在这种情况下,它将开始另一种types的声明。 这是我试过的。
<T: SomeProtocol | SomeOtherProtocol> <T: SomeProtocol , SomeOtherProtocol> <T: SomeProtocol : SomeOtherProtocol>
您可以使用where子句 ,它允许您指定任意数量的需求(所有必须满足的需求),并以逗号分隔
Swift 2:
func someFunc<T where T:SomeProtocol, T:SomeOtherProtocol>(arg: T) { // stuff }
Swift 3:
func someFunc<T: SomeProtocol & SomeOtherProtocol>(arg: T) { // stuff }
或者更强大的where子句:
func someFunc<T>(arg: T) where T:SomeProtocol, T:SomeOtherProtocol{ // stuff }
您当然可以使用协议组合(例如, protocol<SomeProtocol, SomeOtherProtocol>
),但它有点不灵活。
使用where
让你处理涉及多种types的情况。
您可能仍然想要在多个地方编写协议以便重复使用,或者只是为了使协议成为有意义的名称。
你有两种可能性:
-
您使用Jiaaro的答案中指出的where子句 :
func someFunc<T where T : SomeProtocol, T : SomeOtherProtocol>(arg: T) { // do stuff }
-
您使用协议组合types :
func someFunc<T : protocol<SomeProtocol, SomeOtherProtocol>>(arg: T) { // do stuff }
Swift 3.0的演变带来了一些变化。 现在我们的两个select看起来有些不同。
在Swift 3.0中使用where
子句:
现在where
子句已经移到了函数签名的末尾,以提高可读性。 所以多协议inheritance现在看起来像这样:
func someFunc<T>(arg: T) where T:SomeProtocol, T:SomeOtherProtocol { }
在Swift 3.0中使用protocol<>
构造:
使用protocol<>
构造的组合被弃用。 较早的protocol<SomeProtocol, SomeOtherProtocol>
现在看起来像这样:
func someFunc<T:SomeProtocol & SomeOtherProtocol>(arg: T) { }
引用。
更多信息在where
在这里的变化: https : //github.com/apple/swift-evolution/blob/master/proposals/0081-move-where-expression.md
而且,更多的协议<>构造的变化在这里: https : //github.com/apple/swift-evolution/blob/master/proposals/0095-any-as-existential.md
Swift 3提供了多达3种不同的方式来声明你的function。
protocol SomeProtocol { /* ... */ } protocol SomeOtherProtocol { /* ... */ }
1.使用&
运营商
func someFunc<T: SomeProtocol & SomeOtherProtocol>(arg: T) { /* ... */ }
2.使用where
子句
func someFunc<T>(arg: T) where T: SomeProtocol, T: SomeOtherProtocol { /* ... */ }
3.使用where
子句和&
运算符
func someFunc<T>(arg: T) where T: SomeProtocol & SomeOtherProtocol { /* ... */ }
还要注意,你可以使用typealias
来缩短你的函数声明。
typealias RequiredProtocols = SomeProtocol & SomeOtherProtocol func someFunc<T: RequiredProtocols>(arg: T) { /* ... */ }