【问题标题】:Swift: Pass array of type T to a method taking arrays of T's protocolSwift:将类型 T 的数组传递给采用 T 协议数组的方法
【发布时间】:2016-03-16 03:55:01
【问题描述】:

我正在尝试编写一个具有符合MyProto 的对象数组的类,并且我有一种方法可以在将[MyProto] 添加到该数组之前接受各种处理。这是一个游乐场。

protocol MyProto {
    func sayHello()
}

extension MyProto {
    func sayHello() {
        print("hello")
    }
}

struct MyStruct: MyProto {
}

class MyClass {
    var protos: [MyProto] = []
    func doSomethingAndThenStore(newProtos: [MyProto]) {
        for proto in newProtos {
            proto.sayHello()
        }
        protos.appendContentsOf(newProtos)
    }
}

let myStructs = [MyStruct(), MyStruct()]
let myClass = MyClass()
myClass.doSomethingAndThenStore(myStructs)

在最后一行我得到一个错误,error: cannot convert value of type '[MyStruct]' to expected argument type '[MyProto]'。如果我将其更改为myStructs as [MyProto],则错误将更改为error: cannot convert value of type '[MyStruct]' to type '[MyProto]' in coercion

如何将我的具体类型数组传递给接受协议数组的方法?

【问题讨论】:

    标签: swift generics inheritance


    【解决方案1】:

    这个问题源于 Swift 不支持协变泛型。也就是说,Array<Subclass> 不是Array<Superclass>。在这种情况下,即使 MyStructMyProtoArray<MyStruct> 也不是 Array<MyProto>

    Swift 不支持这一点的原因有些复杂,但归根结底是对于某些操作,例如数组检索,将Array<MyStruct> 视为Array<MyProto> 是有效的,但对于其他操作,例如数组插入,关联实际上是相反的。您无法将MyProto 插入Array<MyStruct>,因此不能将Array<MyStruct> 视为Array<MyProto>。其他语言有解决这个问题的机制,但 Swift 目前不支持它们。

    您不能直接传递数组,但是有几种解决方法可以解决这个限制。最简单的是,您可以在数组上映射一个标识函数,以便类型检查器推断出新类型。这将隐式地将每个元素从 MyStruct 分别向下转换为 MyProto

    myClass.doSomethingAndThenStore(myStructs.map { $0 })
    

    您也可以将 MyClass 设为通用并添加类型约束:

    class MyClass<T: MyProto> {
        var protos: [T] = []
        func doSomethingAndThenStore(newProtos: [T]) {
            for proto in newProtos {
                proto.sayHello()
            }
            protos.appendContentsOf(newProtos)
        }
    }
    

    【讨论】:

    • 这很有意义。我想我将为 doSomethingAndThenStore&lt;T: MyProto&gt; 添加一个重载,它会执行映射并调用另一个。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多