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的情况。

您可能仍然想要在多个地方编写协议以便重复使用,或者只是为了使协议成为有意义的名称。

你有两种可能性:

  1. 您使用Jiaaro的答案中指出的where子句

     func someFunc<T where T : SomeProtocol, T : SomeOtherProtocol>(arg: T) { // do stuff } 
  2. 您使用协议组合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) { /* ... */ }