【发布时间】:2017-04-14 20:46:10
【问题描述】:
所以,我有一个泛型(有限制)类和它的许多子类,它们在子类化时具体化泛型类型。
我想将这些子类的实例存储在一个数组中,以便它们可以被迭代并以相同的方式处理它们,但显然,没有办法从子类转换为通用超类。
这是一些说明问题的代码(您可以将其复制粘贴到操场上查看结果):
// Lets create regular classes
class Fruit {
var text: String { return "I am some Fruit" }
}
class Apple: Fruit {
override var text: String { return "I am an Apple" }
}
class Orange: Fruit {
override var text: String { return "I am an Orange" }
}
// This obviously works:
let test1: Fruit = Apple()
let test2: Fruit = Orange()
// Let's create some generic class
class Tree<T: Fruit> {
let fruit: T
init(fruit: T) {
self.fruit = fruit
}
}
// Subclasses from the generic class (these work)
class AppleTree: Tree<Apple> {
convenience init() {
self.init(fruit: Apple())
}
}
class OrangeTree: Tree<Orange> {
convenience init() {
self.init(fruit: Orange())
}
}
// This works:
let tree: Tree<Fruit> = Tree(fruit: Apple())
tree.fruit.text // "I am an Apple"
// This works:
let appleTree1: Tree<Apple> = AppleTree()
appleTree1.fruit.text // "I am an Apple"
// This fails: "Cannot convert value of type 'AppleTree' to specified type 'Tree<Fruit>'
let appleTree2: Tree<Fruit> = AppleTree()
// This works:
let fruitArray: [Fruit] = [Apple(), Orange()]
// THIS IS MY GOAL:
// This fails: "Cannot convert value of type 'AppleTree' to specified type 'Tree<Fruit>'
let treeArray: [Tree<Fruit>] = [AppleTree(), OrangeTree()]
// Let's try with a generic subclass
class FruitTree<T: Fruit>: Tree<T>{}
// This works:
let genericTree: Tree<Fruit> = FruitTree(fruit: Apple())
// Let's try with a generic but more concrete subclass
class GenericOrangeTree<T: Orange>: Tree<T>{
convenience init() {
self.init(fruit: Orange() as! T)
}
}
// This works:
let genericOrangeTree1 = GenericOrangeTree(fruit: Orange())
let genericOrangeTree2 = GenericOrangeTree()
// This fails: Cannot invoke initializer for type 'GenericOrangeTree<Orange>' with an argument list of type '(fruit: Orange)'
let genericTree2: Tree<Fruit> = GenericOrangeTree(fruit: Orange())
// Again, this fails: "Cannot convert value of type 'GenericOrangeTree<Orange>' to specified type 'Tree<Fruit>'
let genericTreeArray: [Tree<Fruit>] = [GenericOrangeTree()]
treeArray 变量在示例代码中说明了我想要做的事情。
我不明白为什么代码在失败时会失败。我的直觉说这应该可行,但我找不到解决此问题的方法。
TL;DR:我有一个带有一些子类的通用类,我想要一个用子类填充的通用类数组,但编译器会抱怨。
【问题讨论】:
-
好吧,你的
SubclassOfGeneric1和SubclassOfGeneric2并没有真正的共同父级,因为每个Generic<T>实际上都会为代码中使用的每个T编译成单独的类。所以Generic<SubClass1>和Generic<SubClass2>和Generic<SuperClass>是三个不相关的类,具有相似的接口。编辑:好吧,Swift 泛型类的编译过程相当复杂,但你应该总是期望它会编译成单独的类。 stackoverflow.com/questions/25917428/…
标签: arrays swift generics subclass