我正在尝试创建一个方法,该方法采用符合Swift中的协议的结构数组。
对于最简单的示例,我定义了一个空协议和一个方法,该方法接受符合该协议的对象数组并打印它们
protocol SomeProtocol {}
func methodTakingProtocol(objects: [SomeProtocol]) {
// do something with the array of objects
print(objects)
}但是,当我尝试向此方法提供符合SomeProtocol的结构数组时,我得到了一个错误
struct SomeStruct: SomeProtocol {}
let arrayOfStructs = [ SomeStruct(), SomeStruct() ]
methodTakingProtocol(arrayOfStructs)
// ^ "Cannot convert value of type '[SomeStruct]' to expected argument type '[SomeProtocol]'"稍微研究一下,我发现我可以通过显式地调用SomeStruct对SomeProtocol的采用来解决这个问题
let arrayOfStructs: [SomeProtocol] = [ SomeStruct(), SomeStruct() ]
// This will work
methodTakingProtocol(arrayOfStructs)有人能告诉我这是怎么回事吗?这是一个我应该提交雷达雷达的bug,还是有一些理由解释为什么编译器不能识别出这个结构数组符合它们被标记为采用的协议?
发布于 2016-04-04 15:45:47
这实际上是按预期工作的。为了将数组传递给方法,您必须强制转换它或显式地将其声明为协议:
protocol SomeProtocol {}
struct SomeStruct: SomeProtocol {}
// explicitly typed
let arrayOfStructs:[SomeProtocol] = [ SomeStruct(), SomeStruct() ]
func foo(bar:[SomeProtocol]) { }
foo(arrayOfStructs) // Works!这里有一篇关于这个主题的优秀文章:Generic Protocols & Their Shortcomings
,但这回避了一个问题:为什么我们不能在泛型约束之外使用泛型协议?
简单的答案是: Swift希望是类型安全的。再加上它是一种提前编译的语言,您的语言需要能够在编译过程中的任何时候推断出具体的类型。我再怎么强调也不为过。在编译时,不是函数/类约束的每个类型都需要是具体的。协议中的关联类型是抽象的。这意味着它们不是具体的。它们是假的。没人喜欢假的。
编辑:这仍然是一篇很棒的文章,但在重新阅读后,我意识到它并不完全适用于这里,因为我们讨论的是“具体协议”,而不是“通用协议”。
https://stackoverflow.com/questions/36396603
复制相似问题