无法初始化嵌套泛型

时间:2017-01-29 03:10:34

标签: swift generics swift3 type-constraints

我试图创建一个类结构,该类结构有一个具有泛型类型(带有类型约束)的类,它被用作另一个泛型类的泛型类型约束。一旦我尝试子类化第一个类型约束类,该子类就不再可用于初始化第二个泛型类(但对第一个类工作正常)。这是一个简化的代码示例:

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>'

那么我可以不使用内部类型泛型约束的子类吗?我可以通过摆脱&#34; ThingWrapper&#34;来解决这个问题。上课,但我试图模仿我的JSON格式,现在我很好奇我做错了什么。

1 个答案:

答案 0 :(得分:1)

当前Swift的实现并不支持这一点,因为它不支持(但)支持泛型中的协方差或逆变,这意味着您需要在专门化类型中完全匹配。

我们可以尝试用更小的例子来简化这个。我们假设我们有以下类层次结构:

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中表达您的类heirarchy,您需要向ThingWrapperList添加另一个通用参数:

class ThingWrapperList<ThingDataType, ThingWrapperType: ThingWrapper<ThingDataType>>: DataClass

在此声明中,ThingWrapperListThingWrapperType ThingDataType上是通用的,因此您可以使用Thing或{{1 }}