【问题标题】:Trouble initializing Nested Generics初始化嵌套泛型时遇到问题
【发布时间】:2017-01-29 03:10:34
【问题描述】:

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

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

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

【问题讨论】:

  • 我认为你来自 java ;) - 更少的继承 - 可能更多的协议。
  • 但为什么不只是简单的结构呢?
  • 你有一个 json 格式的样本,你需要这么多泛型?
  • 也许更面向协议的东西会更好,但这似乎仍然应该有效。任何想法为什么它不?
  • 我没有:我得到了这个class ThingWrapperList&lt;K: Thing, T: ThingWrapper&lt;K&gt;&gt;: DataClass { 在操场上工作 - 没有语法兼容 - 但在运行时它会使编译器崩溃:(

标签: swift generics swift3 type-constraints


【解决方案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 中表达你的类层次结构,你需要在 ThingWrapperList 中添加另一个泛型参数:

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

在此声明中,ThingWrapperListThingWrapperType 的泛型 ThingDataType,因此您可以使用 ThingNewThing 对其进行专门化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-22
    • 1970-01-01
    • 1970-01-01
    • 2011-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-07
    相关资源
    最近更新 更多