说我有这些协议
protocol Actionable {
}
protocol M: class {
associatedtype Action: Actionable
var views: [Action] { get set }
}
和两个函数
func f(view: Actionable) {
}
func g(views: [Actionable]) {
}
我扩展了协议M
extension M {
func add(view: Action) {
views.append(view)
f(view)
g(views)
}
}
当我致电f(view
时,它有效。但是,当我致电g(views)
时,它会显示错误
无法将'[Self.Action]'类型的值转换为预期参数类型'[可操作]'
此处g
接受数组而不是像f
这样的单个对象。为什么数组在这种情况下很重要?如何解决这个问题?
作为旁注,这似乎也是泛型结构的错误
protocol Actionable {
}
struct M<T: Actionable> {
var views: [T]
}
func g(views: [Actionable]) {
}
extension M {
func add() {
g(views)
}
}
答案 0 :(得分:1)
这是Swift中的数组对它们可以隐式转换为的类型有限制这一事实的扩展 - 这是Swift中泛型不变性的结果,我将进一步讨论in this post。
一种可能的解决方案是使用map
将每个元素从Action
单独转换为Actionable
(元素可以自由上传,但数组本身不能):
extension M {
func add(view: Action) {
views.append(view)
f(view)
g(views.map{$0})
}
}
但是,在您的具体情况下,我建议您将f
和g
函数设置为通用,以便维护您提供给它们的具体类型(除非您特别希望它们是类型 - 擦除):
func f<T:Actionable>(view: T) {
...
}
func g<T:Actionable>(views: [T]) {
...
}
的
extension M {
func add(view: Action) {
views.append(view)
f(view)
g(views)
}
}
现在调用它们时会保留Action
的泛型类型,如果你想传递参数,可以提供更好的类型安全性。