1

假设我有这些协议

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]”的值转换为预期的参数类型“[Actionable]”

这里g接受一个数组而不是像f. 为什么在这种情况下数组很重要?如何解决这个问题?

作为旁注,这似乎也是泛型结构的错误

protocol Actionable {

}

struct M<T: Actionable> {
  var views: [T]
}

func g(views: [Actionable]) {

}

extension M {
  func add() {
    g(views)
  }
}
4

1 回答 1

1

这是 Swift 中的数组对它们可以隐式转换为的类型的限制这一事实的扩展——这是 Swift 中泛型不变性的结果,我将在这篇文章中进一步讨论。

一种可能的解决方案是使用map为了将每个元素单独从转换ActionActionable(元素可以自由向上转换,但数组本身不能):

extension M {
    func add(view: Action) {
        views.append(view)
        f(view)
        g(views.map{$0})
    }
}

但是,在您的特定情况下,我只是建议您将fandg函数设为通用,以维护您提供给它们的具体类型(除非您特别希望它们被类型擦除):

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现在,当您调用它们时,将维护通用类型,如果您想传递参数,则为您提供更好的类型安全性。

于 2016-05-29T19:53:47.833 回答