比较Swift中Generic相关类型的类型

时间:2016-04-13 01:48:33

标签: ios swift generics collections protocols

我有下一个代码:

protocol Flyable {
  var airspeedVelocity: Double { get }
}

func topSpeed<T: CollectionType where T.Generator.Element == Flyable>(collection: T) -> Double {
  return collection.map { $0.airspeedVelocity }.reduce(0) { max($0, $1) }
}

我理解,通过阅读Swift Documentation

  

您可以通过将where关键字紧跟在类型参数列表之后,然后是关联类型的约束或类型与关联类型之间的相等关系来编写where子句。

这是文档中给出的示例:

func allItemsMatch<C1: Container, C2: Container where 
C1.ItemType == C2.ItemType, C1.ItemType: Equatable> 
(someContainer: C1, _ anotherContainer: C2) -> Bool {
    // code
}

请注意,在表示ItemType类型的关联类型C1必须符合Equatable协议时,您使用:而不是==,为什么在我的示例中并非如此,我必须使用==来声明Element相关联的T.Generator类型必须符合Flyable

使用==更改:时,编译器会抱怨:

  

错误:无法调用&#39; topSpeed&#39;使用类型&#39;([Flyable])&#39;的参数列表注意:期望一个类型为&#39;(T)&#39;

的参数列表

2 个答案:

答案 0 :(得分:0)

您可以在不使用Generics的情况下实现此目的。

protocol Flyable {
    var airspeedVelocity: Double { get }
}

func topSpeed(collection: [Flyable]) -> Double {
    return collection.map { $0.airspeedVelocity }.reduce(0) { max($0, $1) }
}

class Airplane: Flyable {

    var airspeedVelocity: Double = 10

}

class Rocket: Flyable {

    var airspeedVelocity: Double = 50

}

topSpeed([Airplane(),Rocket()]) //50

答案 1 :(得分:0)

我找到了原因here。 where子句具有下一个语法:

conformance-requirement → type-identifier­:­type-identifier­
same-type-requirement → type-identifier­==­type­

因此,当您想声明您的类型参数符合某个协议时,请使用:。但是,当您希望类型完全属于某种类型时,请使用==。在我的示例中,我想将Flyable的集合作为参数。因此,在尝试使用:时,编译器会抱怨,因为Flyable不符合FlyableFlyableFlyable,因此我必须使用==(或者像@Rahul Katariya所做的那样做)