Swift Element 的通用集合无法转换为 Any 的集合

Swift generic collection of Element cannot convert to collection of Any

我遇到了一个我不明白的问题。 在我的项目中,我想用一些自定义方法(比如从服务器更新)来制作元素集合。但是,当我尝试将所有这些集合分组到一个数组中时,出现错误:“无法将类型 MyCollection<someElement> 的值转换为预期的参数类型 MyCollection<Any>

我不明白的是,与 Array 相同的代码正在运行...Array 不是集合?

// My collection which would contain an update method
class MyCollection<Element> {
    var object:Element? = nil
}

let x = MyCollection<Int>()
var list = [MyCollection<Any>]()
list.append(x) //Cannot convert value of type 'MyCollection<In>' to expected argument type 'MyCollection<Any>'

let a = Array<Int>()
var lista = [Array<Any>]()
lista.append(a) //Doesn't get error at all...

我知道我可以使用特定类型的数组来执行此操作,但是通过将所有 MyCollection 分组到一个数组中,我希望使用如下代码:

func update() {
    for e in list { // array of MyCollection<Any>
        e.update()
    }
}

提前感谢您的帮助 ;)

能够从SomeType<Subtype>转换为SomeType<Supertype>称为协方差。在 Swift、Array<T> is covariant on T by "compiler magic", and you can't do the same for your own types.

The type checker hardcodes conversions from Array to Array if there is a conversion from T to U. Similar rules exist for Optional and Dictionary. There's no mechanism for doing this with your own types.

您自己的泛型类型总是不变的,这意味着只要 TU 是不同的类型,就永远不会在 SomeType<T>SomeType<U> 之间进行转换.

让我们想象一下如果允许 MyCollection 上的转换会发生什么。你可以这样做:

let myCollectionInt = MyCollection<Int>()
let myCollectionAny: MyCollection<Any> = myCollectionInt // suppose you can do this
myCollectionAny.object = "string" // myCollectionAny.object is of type Any?, so this should be ok

我们已经将myCollectionAny.object设置为“string”,但是MyCollection是引用类型,所以myCollectionInt.object也应该是“string”。但是 myCollectionInt.objectInt?!

当然这 type-unsafety 也是数组的一个问题,但是语言设计者已经决定转换数组是一件很常见的事情,不允许这样做会弊大于利。