在Swift数组中存储通用对象

时间:2014-10-16 03:14:48

标签: generics swift

写下以下小测试:

class Model { }
class SubModel : Model {}
class Collection<T: Model> {}

let collection = Collection<SubModel>()
var collections = [Collection]() // Also tried [Collection<Model>]() 
collections.append(collection)

编译器在追加调用时失败。消息是:'SubModel'与'Model'不同。 根据我在泛型中使用的所有其他语言的经验,这应该有效。作为类型SubMode的集合应该始终可以强制到Model类型的集合。 有人碰到这个吗?解决方法?

1 个答案:

答案 0 :(得分:5)

这种情况正在发生,因为Swift在泛型类型参数方面不支持covariance

例如:

class Animal {}
class Cat : Animal {}

Cat显然是Animal的子类型。但是,这并不意味着,Array<Cat>Array<Animal>的子类型。在支持泛型类型参数协方差的语言(例如C#)中,Array<Cat>将是Array<Animal>的子类型。

在您的特定示例中,您可以使用协议和非泛型 Collection类来解决此限制。其他情况可能需要更多的创造力。

protocol Collectible {}
class Model : Collectible {}
class SubModel : Model {}

class Collection {
    func append(element: Collectible) {
        // blah
    }
}

var collection = Collection()
collection.append(Model())
collection.append(SubModel())
var collections = [collection]

实际上,在您的情况下,您可以将Collection的元素设为Model,即func append(element: Model),但我这样做是为了强调协议有时可能是习惯于解决协方差限制。