我正在尝试创建一个方法,该方法采用符合 Swift 协议(protocol)的结构数组。
对于最简单的示例,我定义了一个空协议(protocol)和一个方法,该方法采用符合该协议(protocol)的对象数组并只打印它们
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)
谁能告诉我这是怎么回事?这是一个我应该提交雷达的错误,还是有一些关于为什么编译器不能将这个结构数组识别为符合它们被标记为采用的协议(protocol)的推理?
最佳答案
这实际上是按预期工作的。为了将数组传递给方法,您必须强制转换它或将其显式声明为协议(protocol):
protocol SomeProtocol {}
struct SomeStruct: SomeProtocol {}
// explicitly typed
let arrayOfStructs:[SomeProtocol] = [ SomeStruct(), SomeStruct() ]
func foo(bar:[SomeProtocol]) { }
foo(arrayOfStructs) // Works!
这是一篇关于此主题的优秀文章:Generic Protocols & Their Shortcomings
But that begs the question; Why can't we use generic protocols outside of generic constraints?
The short answer is: Swift wants to be type-safe. Couple that with the fact that it's an ahead-of-time compiled language, and you have a language that NEEDS to be able to infer a concrete type at anytime during compilation. I can't stress that enough. At compile time, every one of your types that aren't function/class constraints need to be concrete. Associated types within a protocol are abstract. Which means they aren't concrete. They're fake. And no one likes a fake.
编辑:它仍然是一篇很棒的文章,但在重新阅读后我意识到它并不完全适用于此,因为我们讨论的是“具体协议(protocol)”而不是“通用协议(protocol)”。
关于swift - 不识别符合协议(protocol)的结构数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36396603/