无法初始化嵌套泛型
Trouble initializing Nested Generics
我正在尝试创建一个 class 结构,其中有一个 class 具有通用类型(具有类型约束),用作另一个通用类型的通用类型约束 class。一旦我尝试 subclass 第一个类型约束 class,subclass 就不再可用于初始化第二个泛型 class (但对第一个可以正常工作).这是一个简化的代码示例:
class DataClass {
var value: Int
required init(value: Int) {
self.value = value
}
}
class Thing: DataClass {
required init(value: Int) {
super.init(value: value)
}
}
class ThingWrapper<ThingDataType: Thing>: DataClass {
var thing: ThingDataType
required init(value: Int) {
thing = ThingDataType(value: value)
super.init(value: value)
}
}
class ThingWrapperList<ThingWrapperType: ThingWrapper<Thing>>: DataClass {
var things: [ThingWrapperType]
required init(value: Int) {
things = [ThingWrapperType]()
super.init(value: value)
}
}
这些工作正常:
var thingWrapper = ThingWrapper<Thing>(value: 42)
var thingWrapperList = ThingWrapperList<ThingWrapper<Thing>>(value: 42)
这样做:
class NewThing: Thing {
required init(value: Int) {
super.init(value: value)
}
}
var newThingWrapper = ThingWrapper<NewThing>(value: 42)
但这会产生错误:
var newThingWrapperList = ThingWrapperList<ThingWrapper<NewThing>>(value: 42)
Error: 'ThingWrapperList' requires that 'ThingWrapper<NewThing>' inherit from 'ThingWrapper<Thing>'
那么我可以不使用内部类型泛型约束的子class吗?我可能可以通过摆脱 "ThingWrapper" class 来解决这个问题,但我试图模仿我的 JSON 格式,现在我很好奇我做错了什么。
Swift 的当前实现不支持这一点,因为它(还)不支持泛型中的协变或逆变,这意味着您需要在专用类型中进行精确匹配。
我们可以尝试用一个更小的例子来简化它。假设我们有以下 class 层次结构:
class A1 {}
class A2: A1 {}
class B1<T: A1> {}
class B2<T: A1>: B1<T> {}
我们可以检查 Swift 执行的规则:
// These first 3 assignments compile correctly:
let a: A1 = A2() // because A2 inherits from A1
let b: B1<A1> = B2<A1>() // because B2 inherits from B1 and A1 == A1
let b2: B1<A2> = B2<A2>() // because B2 inherits from B1 and A2 == A2
// The next 2 assignments do not compile in current Swift
// due to the lack of covariant generics
let b3: B1<A1> = B1<A2>() // cannot convert value of type 'B1<A2>' to specified type 'B1<A1>'
let b4: B1<A1> = B2<A2>() // cannot convert value of type 'B2<A2>' to specified type 'B1<A1>'
为了重现您的问题,我们需要添加另一层,所以让我们创建一个函数:
func C<T: A1>(_ arg: B1<T>) {}
C(B1<A1>())
C(B1<A2>())
C(B2<A1>())
C(B2<A2>())
这一切都编译成功,因为我们添加了另一个通用参数来处理所需的专业化,而不是试图依赖协方差。
总而言之,要在 Swift 中表达您的 class 层次结构,您需要向 ThingWrapperList
添加另一个通用参数:
class ThingWrapperList<ThingDataType, ThingWrapperType: ThingWrapper<ThingDataType>>: DataClass
在此声明中,ThingWrapperList
在 ThingWrapperType
和 ThingDataType
上是通用的,因此您可以将其专门化为 Thing
] 或 NewThing
.
我正在尝试创建一个 class 结构,其中有一个 class 具有通用类型(具有类型约束),用作另一个通用类型的通用类型约束 class。一旦我尝试 subclass 第一个类型约束 class,subclass 就不再可用于初始化第二个泛型 class (但对第一个可以正常工作).这是一个简化的代码示例:
class DataClass {
var value: Int
required init(value: Int) {
self.value = value
}
}
class Thing: DataClass {
required init(value: Int) {
super.init(value: value)
}
}
class ThingWrapper<ThingDataType: Thing>: DataClass {
var thing: ThingDataType
required init(value: Int) {
thing = ThingDataType(value: value)
super.init(value: value)
}
}
class ThingWrapperList<ThingWrapperType: ThingWrapper<Thing>>: DataClass {
var things: [ThingWrapperType]
required init(value: Int) {
things = [ThingWrapperType]()
super.init(value: value)
}
}
这些工作正常:
var thingWrapper = ThingWrapper<Thing>(value: 42)
var thingWrapperList = ThingWrapperList<ThingWrapper<Thing>>(value: 42)
这样做:
class NewThing: Thing {
required init(value: Int) {
super.init(value: value)
}
}
var newThingWrapper = ThingWrapper<NewThing>(value: 42)
但这会产生错误:
var newThingWrapperList = ThingWrapperList<ThingWrapper<NewThing>>(value: 42)
Error: 'ThingWrapperList' requires that 'ThingWrapper<NewThing>' inherit from 'ThingWrapper<Thing>'
那么我可以不使用内部类型泛型约束的子class吗?我可能可以通过摆脱 "ThingWrapper" class 来解决这个问题,但我试图模仿我的 JSON 格式,现在我很好奇我做错了什么。
Swift 的当前实现不支持这一点,因为它(还)不支持泛型中的协变或逆变,这意味着您需要在专用类型中进行精确匹配。
我们可以尝试用一个更小的例子来简化它。假设我们有以下 class 层次结构:
class A1 {}
class A2: A1 {}
class B1<T: A1> {}
class B2<T: A1>: B1<T> {}
我们可以检查 Swift 执行的规则:
// These first 3 assignments compile correctly:
let a: A1 = A2() // because A2 inherits from A1
let b: B1<A1> = B2<A1>() // because B2 inherits from B1 and A1 == A1
let b2: B1<A2> = B2<A2>() // because B2 inherits from B1 and A2 == A2
// The next 2 assignments do not compile in current Swift
// due to the lack of covariant generics
let b3: B1<A1> = B1<A2>() // cannot convert value of type 'B1<A2>' to specified type 'B1<A1>'
let b4: B1<A1> = B2<A2>() // cannot convert value of type 'B2<A2>' to specified type 'B1<A1>'
为了重现您的问题,我们需要添加另一层,所以让我们创建一个函数:
func C<T: A1>(_ arg: B1<T>) {}
C(B1<A1>())
C(B1<A2>())
C(B2<A1>())
C(B2<A2>())
这一切都编译成功,因为我们添加了另一个通用参数来处理所需的专业化,而不是试图依赖协方差。
总而言之,要在 Swift 中表达您的 class 层次结构,您需要向 ThingWrapperList
添加另一个通用参数:
class ThingWrapperList<ThingDataType, ThingWrapperType: ThingWrapper<ThingDataType>>: DataClass
在此声明中,ThingWrapperList
在 ThingWrapperType
和 ThingDataType
上是通用的,因此您可以将其专门化为 Thing
] 或 NewThing
.