【问题标题】:Array of slightly different generics略有不同的泛型数组
【发布时间】:2018-02-21 20:04:20
【问题描述】:

我有一个采用泛型类型的类,它必须继承自类WorldObject

class WorldObjectsProvider<WorldObjectType: WorldObject> 

这个类将创建类WorldObjectType 的对象并在一个函数中返回它们。现在我想创建一个此类类的数组(WorldObjectsProvider),但我希望这个数组能够保留许多不同类型的泛型类WorldObjectsProvider,例如:

class TestObject: WorldObject { }
let providers: [WorldObjectsProvider<WorldObject>] = [WorldObjectsProvider<WorldObject>(), WorldObjectsProvider<TestObject>()]

总的来说,我认为这是可能的,因为所有泛型类型都应该继承自 WorldObject。这可以通过返回所有值作为对基类WorldObject 的引用来实现。但我想这对于泛型来说可能太多了。有没有办法创建这样的数组?

【问题讨论】:

  • 泛型在参数方面是不变的,因此你需要的东西更难实现。
  • 所有泛型类都是不同的类型,具体取决于泛型类型参数,并且 Swift 泛型类不是协变的,因此即使 BA 的子类,Generic&lt;A&gt;Generic&lt;B&gt; 也不相关.
  • 您可能需要重新考虑这种方法。也许创建协议类型数组...一般来说,我看不到使用完全不同类型的数组...

标签: swift generics


【解决方案1】:

Swift 泛型类型在其泛型参数方面是不变的,这意味着 MyGeneric&lt;A&gt;MyGeneric&lt;B&gt; 不兼容,即使 A: B 也是如此。

话虽如此,如果您需要使用两个不同的泛型,则需要两个泛型的共同点。类型橡皮擦是可能的解决方案之一:

struct AnyProvider<T: WorldObject> {
    init<U: WorldObject>(_ provider: WorldObjectsProvider<U>) { }
}

let providers: [AnyProvider<WorldObject>] = [AnyProvider(WorldObjectsProvider<WorldObject>()), AnyProvider(WorldObjectsProvider<TestObject>())]

这将允许您在同一个集合中使用多种类型的泛型,前提是它们具有共同点。缺点是类型擦除器可能必须模仿和转发原始类型的所有公共方法。

例如,如果原始提供者有一个func someProviderMethod() 方法,那么AnyProvider 也必须声明它:

struct AnyProvider<T: WorldObject> {
    private let _someProviderMethod: () -> Void

    init<U: WorldObject>(_ provider: WorldObjectsProvider<U>) {
        _someProviderMethod = provider.someProviderMethod
    }

    func someProviderMethod() {
        _someProviderMethod()
    }
}

【讨论】:

  • 我可以将所有内容向下转换为基本类型,但我以后如何从这个容器中检索提供程序?我尝试在该结构中创建 let 并在初始化程序中分配它,但无法做到。
  • @DamianDudycz 在更新的答案中添加了一个示例。
  • 哇,这有点复杂,但可以按我的需要工作:)。我要试验一下,谢谢。
  • 原来我的结构有点太复杂了,并且导致了更多的问题,我无法用这些泛型类很好地解决。我最终转换了代码,始终通过基类引用返回对象,并且在提供程序中我有包含 WorldObject 类型的开放 var。如果我想编写一个返回 WorldObjects 子类的 provider 子类,我现在可以重写这个 var,剩下的问题就解决了,因为外部 provider 子类我需要使用 WorldObjects 的基类。
猜你喜欢
  • 1970-01-01
  • 2012-06-25
  • 2023-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-25
  • 1970-01-01
  • 2015-03-22
相关资源
最近更新 更多