我想使用泛型类和类型约束:
class MyCustomClass<T : Equatable> {
var a: Array<T>
init() {
a = Array<T>()
}
}
Run Code Online (Sandbox Code Playgroud)
这很好.但是,如果我想使用第二个协议,会发生什么
class MyCustomClass<T : Equatable, IndexableBase> {
var a: Array<T>
init() {
a = Array<T>()
}
}
Run Code Online (Sandbox Code Playgroud)
它说初始化程序失败了,因为我必须使用2而不是1个参数.我不明白.
dfr*_*fri 17
斯威夫特3
(我在你的例子中替换IndexableBase了Collection你应该更喜欢后者)
根据Swift 3,协议组合使用中缀运算符&而不是之前的protocol<...>构造,如接受和实现的进化提议中所述:
因此,使用协议组合,您可以将组合类型约束放在T参数列表中的占位符中:
class MyCustomClass<T: Equatable & Collection> { /* ... */ }
Run Code Online (Sandbox Code Playgroud)
作为协议组合的替代方法,您还可以使用where子句来连接多个类型(和子类型)约束.根据已接受和实施的进化建议:
该where子句已移至声明的末尾,在这种情况下,您的示例将如下所示:
class MyCustomClass<T: Equatable> where T: Comparable { /* ... */ }
Run Code Online (Sandbox Code Playgroud)
或者,甚至将完整的协议组成与where声明末尾的条款放在一起
class MyCustomClass<T> where T: Equatable & Comparable { /* ... */ }
Run Code Online (Sandbox Code Playgroud)
我们应该选择哪种风格?
有趣的讨论是我们应该考虑的"最佳实践",因为这个特定主题没有指定Swift API指南.我们放置
考虑下面的设计示例,其中我们有一个构造协议,我们计划将其用作类型约束(Doable),它本身包含一个associatedtype我们可以放置类型约束的类型.
protocol Doable {
associatedtype U
}
Run Code Online (Sandbox Code Playgroud)
使用上面的不同方法,以下三个替代方法在语法上都是有效的
// 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 { /* ... */ }
Run Code Online (Sandbox Code Playgroud)
我将引用苹果开发人员Joe Groff从SE-0081提出的演变主题:
这是一个判断电话.我觉得在很多情况下,一个通用参数至少受到一个值得提前调用的重要协议或基类的限制,因此允许这样的事情是合理的.
Run Code Online (Sandbox Code Playgroud)func foo<C: Collection>(x: C) -> C.Element没有将
Collection约束放在距离声明前面太远的地方.
因此,在上面的设计示例中,可能适合将协议组合用于直接应用于通用占位符的类型约束,T并将这些约束放在参数列表中,而子类型约束T.U放在声明的末尾.即,上面的替代#1.
你可以使用这个解决方法
class MyCustomClass<T: Equatable where T: IndexableBase > {
var a: Array<T>
init() {
a = Array<T>()
}
}
Run Code Online (Sandbox Code Playgroud)
斯威夫特4:
class MyCustomClass<T: Equatable> where T: Collection {
var a: Array<T>
init() {
a = Array<T>()
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1798 次 |
| 最近记录: |