2016-12-07 35 views
6

一个协议,我想用一个通用的类型化类和类型约束:超过一个类型约束

class MyCustomClass<T : Equatable> { 
    var a: Array<T> 
    init() { 
    a = Array<T>() 
    } 
} 

这工作正常。但是如果我想使用第二个协议f.e.会发生什么?

class MyCustomClass<T : Equatable, IndexableBase> { 
    var a: Array<T> 
    init() { 
    a = Array<T>() 
    } 
} 

它说,初始值设定项失败,因为我必须使用2而不是1参数。我不明白。

回答

1

您可以使用此解决方案

class MyCustomClass<T: Equatable where T: IndexableBase > { 
    var a: Array<T> 
    init() { 
     a = Array<T>() 
    } 
} 
+0

Where运算符适合我(Xcode 8.1,Swift 3),所以我使用这个解决方案。 – altralaser

+2

@altralaser即使这个在你的Swift 3中“起作用”,它应该给你一个警告,即[** emphasis ** mine]:_“warning:'where''子句旁边的通用参数**已被弃用并且将在未来版本的Swift **“_”中被删除。因此,您可能希望使用Swift 3的最新解决方案,否则您的实现将在Swift的未来更新中被破解(请参阅Swift 3最新版本的其他两个答案)。 – dfri

14

斯威夫特3

(我已经在你的榜样取代IndexableBaseCollection,你应该更喜欢后者)


按照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。

+0

这令人印象深刻!但是你对[这个建议]有什么看法(https://github.com/apple/swift-evolution/blob/master/proposals/0081-move-where-expression.md)?我回答的基础上... btw我不是downvoter,我是upvoter :) –

+0

@AhmadF谢谢。这个建议也包含在我的答案中,我相信它和新的协议组合(同一概念的两个部分)是一样的。有趣的讨论是我们应该考虑的最佳实践,因为它在Swift API指南中没有详细说明。我们是否将所有约束放在声明的末尾,还是仅限于子类型约束?有一个有趣的讨论与SE-0081的演化提案有关,其中包含一些想法以及在哪里放置不同约束的优缺点;在我的回答中,我将包括一点这个讨论。 – dfri

+0

说实话我发现是“冷却器”,我不知道它存在! –