gpt4 book ai didi

arrays - Swift - 如何在数组中存储泛型的子类

转载 作者:搜寻专家 更新时间:2023-10-31 21:49:15 25 4
gpt4 key购买 nike

所以,我有一个泛型(有限制)类和它的一些子类,它们在子类化时具体化了泛型类型。

我想将这些子类的实例存储在一个数组中,以便可以迭代它们并以相同的方式处理它们,但显然,没有办法从子类转换为通用父类(super class)。

下面是一些说明问题的代码(您可以在 playground 中复制粘贴它以查看结果):

// 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:我有一个带有一些子类的泛型类,我想要一个由子类填充的泛型类数组,但编译器报错。

最佳答案

您混淆了泛型具体化前后的类型层次结构。使用通用类/函数,您实际上设置了一个在编译时解析的模板(编译器宏)。

如果你说

Generic<SubClass1>
Generic<SuperClass>

那些被编译器解析为如下类型:

class Generic_SubClass1 {
let property : SubClass1
}
class Generic_SuperClass {
let property : SuperClass
}

解析泛型后,这两种类型不共享公共(public)基类型,因此不能相互转换。它们是完全独立的。

不确定也没有尝试,但也许这就是您想要的:

class GenericBase {
let property : SuperClass
}
class Generic<T: SuperClass> : GenericBase {
final var typedProperty : T {
get { return property as T }
set { property = T }
}
}

然后您可以使用 GenericBase 作为公共(public)祖先并使用动态类型来检查子类。

P.S.:您的代码有点难以理解,可以使用“水果”、“苹果”和“橙子”之类的东西 - 比“父类(super class)”、“子类 1”、“子类 2”更容易阅读;-)

关于arrays - Swift - 如何在数组中存储泛型的子类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40889875/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com