我有一个基类ItemBase
和一个类CollectionBase
,其中的项目类型为ItemBase
。
我从这个ItemBase
- PersonItem
和AnimalItem
派生了两个类。
我使用相应的项目CollectionBase
和PersonCollection
从AnimalCollection
派生了两个类。
然后我创建了一个CollectionBase
- ItemBase
类型的数组。
现在我想将PersonCollection
和AnimalCollection
附加到数组中,但是我收到以下错误:
"无法指定类型' PersonCollection'的值输入 '数据收集"
如何定义集合数组,我可以根据CollectionBase
- ItemBase
附加项目?
class ItemBase {
}
class CollectionBase<T: ItemBase> {
var Items = [T]()
}
class PersonItem: ItemBase {
}
class PersonCollection: CollectionBase<PersonItem> {
}
class AnimalItem: ItemBase {
}
class AnimalCollection: CollectionBase<AnimalItem> {
}
var collection = [CollectionBase<ItemBase>]()
// Error: Cannot assign value of type 'PersonCollection' to type 'DataCollection<ItemBase>
collection.append(PersonCollection())
// Error: Cannot assign value of type 'AnimalCollection' to type 'DataCollection<ItemBase>
collection.append(AnimalCollection())
答案 0 :(得分:2)
首先,您的示例包含一些关于编译器(正确)无法接受的类型系统的矛盾陈述。
为了那个时刻&#39;,请阅读variance and contravariance on Wikipedia。否则,继续阅读。
你的例子在这里失败的原因是
var collection = [CollectionBase<ItemBase>]()
定义了一个类数组,您可以使用ItemBase类的项访问和更新Items
成员属性。
然后,您尝试追加违反此要求的数组元素PersonCollection()
- 它不允许向其项目成员添加ItemBase。
其次,因为
PersonCollection继承自ItemBase
您正在阅读以下内容:
SomeGeneric&LT; PersonCollection&GT;继承自SomeGeneric&lt; ItemBase&gt;
虽然这对你来说可能是完全合理的,但是快速语言中没有任何东西可以实现这一点。
你可以在这里合理地指出 swift集合类似乎可以正常管理 - 如下所示:
class ItemBase {
}
class PersonItem: ItemBase {
}
class AnimalItem: ItemBase {
}
var collection = [Array<ItemBase>]()
collection.append([PersonItem]())
它确实如此,但不幸的是它这样做是因为swift语言对内置集合类型(如Array
)有特殊规则。 As far as I know你不能仅使用快速代码独立实现Array。
那么如何处理呢?
在您解决设计中的上述不一致之前,您不能。但是,我认为这些功能只是根据您所使用的语言解决问题的方法。
您可以使用swift的内置Array类。
或者您可以定义一个在基础上不通用的不同继承层次结构:
例如 - 在基础上使用协议(或类),它肯定适用于ItemBase对象(没有关联的类型要求)。
protocol ItemCollection {
var items:[ItemBase] { get }
}
class ThingCollection<Thing:ItemBase>:ItemCollection {
var things:[Thing] = []
var items:[ItemBase] {
return things
}
}
typealias PersonCollection = ThingCollection<PersonItem>
var itemCollection:[ItemCollection] = []
itemCollection.append(PersonCollection())
答案 1 :(得分:0)
为什么需要额外的间接?有什么问题:
class ItemBase {
}
class PersonItem: ItemBase {
}
class AnimalItem: ItemBase {
}
var collection = [ItemBase]()
collection.append(PersonItem())
collection.append(AnimalItem())
或者:
class ItemBase {
}
class PersonItem: ItemBase {
}
class AnimalItem: ItemBase {
}
var collection = [[ItemBase]]()
collection.append([PersonItem]())
还有可能:
class ItemBase {
}
class PersonItem: ItemBase {
}
class AnimalItem: ItemBase {
}
class CollectionBase<T: ItemBase> {
var Items = [T]()
}
class PersonCollection: CollectionBase<PersonItem> {
}
class AnimalCollection: CollectionBase<AnimalItem> {
}
let personCollection = PersonCollection()
personCollection.Items.append(PersonItem())
但我认为你想要的额外间接在Swift中是不可能的。你可以解决它,但是失去了严格的类型安全性:
var collection = [AnyObject]()
collection.append(PersonCollection())
collection.append(AnimalCollection())
if collection[0] is PersonCollection {
// ...
}