Swift 中的多类型约束

假设我有这些协议:

protocol SomeProtocol {


}


protocol SomeOtherProtocol {


}

现在,如果我想要一个采用泛型类型的函数,但该类型必须符合 SomeProtocol,我可以这样做:

func someFunc<T: SomeProtocol>(arg: T) {
// do stuff
}

但是有没有为多个协议添加类型约束的方法呢?

func bothFunc<T: SomeProtocol | SomeOtherProtocol>(arg: T) {


}

类似的事情使用逗号,但是在这种情况下,它将启动一个不同类型的声明。这是我试过的方法。

<T: SomeProtocol | SomeOtherProtocol>
<T: SomeProtocol , SomeOtherProtocol>
<T: SomeProtocol : SomeOtherProtocol>
48453 次浏览

您可以使用 哪里条款,它允许您指定任意数量的需求(所有这些需求都必须满足) ,并以逗号分隔

斯威夫特2:

func someFunc<T where T:SomeProtocol, T:SomeOtherProtocol>(arg: T) {
// stuff
}

迅捷3 & 4:

func someFunc<T: SomeProtocol & SomeOtherProtocol>(arg: T) {
// stuff
}

或者更有力的 where 条款:

func someFunc<T>(arg: T) where T:SomeProtocol, T:SomeOtherProtocol{
// stuff
}

当然可以使用协议组合(例如 protocol<SomeProtocol, SomeOtherProtocol>) ,但是灵活性稍差。

使用 where可以处理涉及多种类型的情况。

您可能仍然希望编写协议以便在多个地方重用,或者仅仅是为编写的协议提供一个有意义的名称。

迅捷5:

func someFunc(arg: SomeProtocol & SomeOtherProtocol) {
// stuff
}

这样感觉更自然,因为协议就在争论的旁边。

你有两种可能:

  1. 如 Jiaaro 的答案所示,你使用的是 其中子句 :

    func someFunc<T where T : SomeProtocol, T : SomeOtherProtocol>(arg: T) {
    // do stuff
    }
    
  2. You use a protocol composition type:

    func someFunc<T : protocol<SomeProtocol, SomeOtherProtocol>>(arg: T) {
    // do stuff
    }
    

Swift 3.0的发展带来了一些变化,我们的两个选择现在看起来有点不同。

在 Swift 3.0中使用 where子句:

为了提高可读性,where子句现在移到了函数签名的末尾。所以多协议继承现在看起来像这样:

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

而且,更多关于 protocol < > 结构的更改在这里: https://github.com/apple/swift-evolution/blob/master/proposals/0095-any-as-existential.md

Swift 3提供了3种不同的函数声明方式。

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) {
/* ... */
}