我正在尝试创建一个方法,该方法采用符合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)
有人能告诉我这里发生了什么吗?这是一个我应该提交雷达的错误,还是有一些理由说明为什么编译器不能识别这个结构数组符合它们被标记为采用的协议?
答案 0 :(得分:0)
这实际上是按预期工作的。为了将数组传递给方法,您必须将其转换或显式声明为协议:
protocol SomeProtocol {}
struct SomeStruct: SomeProtocol {}
// explicitly typed
let arrayOfStructs:[SomeProtocol] = [ SomeStruct(), SomeStruct() ]
func foo(bar:[SomeProtocol]) { }
foo(arrayOfStructs) // Works!
以下是关于此主题的优秀文章:Generic Protocols & Their Shortcomings
但这引出了一个问题;为什么我们不能在外面使用通用协议 通用约束?
简短的回答是:Swift希望是类型安全的。结合那个 事实上,它是一种提前编译的语言,你有一个 需要能够随时推断出具体类型的语言 在编译期间。我不能强调这一点。在编译时,每一个 你需要的一个类型不是函数/类约束 具体。协议中的关联类型是抽象的。意思是 他们不是具体的。他们是假的。没有人喜欢假的。
编辑:它仍然是一篇很棒的文章,但在重新阅读后,我意识到它并不完全适用于此,因为我们讨论的是“具体协议”,而不是“通用协议”。