如何使用关联类型和数组扩展协议
How to make extension to protocol using associatedtype and array
假设我有这些协议
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)
它显示错误
Cannot convert value of type '[Self.Action]' to expected argument type '[Actionable]'
这里 g
接受数组而不是像 f
这样的单个对象。为什么数组在这种情况下很重要?如何解决这个问题?
附带说明一下,这似乎也是通用结构的错误
protocol Actionable {
}
struct M<T: Actionable> {
var views: [T]
}
func g(views: [Actionable]) {
}
extension M {
func add() {
g(views)
}
}
这是对以下事实的扩展:Swift 中的数组对其可以隐式转换为的类型有限制——这是我讨论的 Swift 中泛型不变性的结果进一步 .
一个可能的解决方案是使用 map
以便将每个元素单独从 Action
转换为 Actionable
(元素可以自由向上转换,但数组本身不能):
extension M {
func add(view: Action) {
views.append(view)
f(view)
g(views.map{[=10=]})
}
}
然而,在您的具体情况下,我只是建议使您的 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
的泛型类型将得到维护,如果您想传递参数,则可以提供更好的类型安全性。
假设我有这些协议
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)
它显示错误
Cannot convert value of type '[Self.Action]' to expected argument type '[Actionable]'
这里 g
接受数组而不是像 f
这样的单个对象。为什么数组在这种情况下很重要?如何解决这个问题?
附带说明一下,这似乎也是通用结构的错误
protocol Actionable {
}
struct M<T: Actionable> {
var views: [T]
}
func g(views: [Actionable]) {
}
extension M {
func add() {
g(views)
}
}
这是对以下事实的扩展:Swift 中的数组对其可以隐式转换为的类型有限制——这是我讨论的 Swift 中泛型不变性的结果进一步
一个可能的解决方案是使用 map
以便将每个元素单独从 Action
转换为 Actionable
(元素可以自由向上转换,但数组本身不能):
extension M {
func add(view: Action) {
views.append(view)
f(view)
g(views.map{[=10=]})
}
}
然而,在您的具体情况下,我只是建议使您的 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
的泛型类型将得到维护,如果您想传递参数,则可以提供更好的类型安全性。