【问题标题】:Instantiate collection without knowing concrete type在不知道具体类型的情况下实例化集合
【发布时间】:2019-06-18 17:11:28
【问题描述】:

我有一个类是通用的类型 T,它符合 Collection 协议。现在我想在不知道集合的具体类型的情况下实例化集合,这可能吗?

class FileStore<T: Collection>{

   var collection: T

   init(){
      collection = T() // This will never work
   }

}

【问题讨论】:

  • 我很好奇这解决了什么问题。然后你会如何处理collection,它不关心它是有序的还是唯一的,也不关心元素类型是什么?
  • 另外,由于结果集合不承诺是可变的,你将如何使用它?
  • Rob 我正在尝试制作一个灵活的文件存储。我希望能够序列化任何集合并将其保存到文件并再次检索它...集合变量用于“缓存”当应用程序进入后台时数据将被持久化。

标签: swift generics collections


【解决方案1】:

Collection 在其协议要求中没有init,因此您不能直接初始化Collection 实例。你有几个解决方案。您可以将泛型类型约束限制为保证具有 init 的类型(例如 Array),或者您可以创建自己的需要 init 的协议,使 T 要求符合该协议并扩展所有 @987654328 @s 您希望能够存储以符合您的协议。

第二种方法如下所示:

protocol Initializable {
    init()
}

class FileStore<T: Collection> where T: Initializable {
    var collection: T

    init(){
        collection = T.init()
    }
}

// Extend the `Collection` conformant types
extension Array: Initializable {}
extension Dictionary: Initializable {}
extension Set: Initializable {}

// Create a FileStore
FileStore<Array<Int>>()
FileStore<[String:Int]>()
FileStore<Set<String>>()

或者根据您想要存储的确切类型,使用内置的RangeReplaceableCollection 作为您的类型约束会更好。 (请记住,相当多的标准库类型不符合 RangeReplaceableCollection,但它们确实符合 Collection 并且具有空 init,例如 DictionarySet 等)。

class OtherFileStore<T: RangeReplaceableCollection> {
    var collection = T.init()
}

【讨论】:

  • 比起T: Initializable,我建议T: RangeReplaceableCollection。它提供了相同的好处,但具有适当的语义,并且恰好是内置的。 “Initializable”不会告诉您任何有关结果集合的信息(它甚至可能无效)。 RangeReplaceableCollection 要求结果集合为空。
  • 为了包含Set,您还需要为: SetAlgebra 提供一个版本,它提供相同的“init promises empty”语义。有关我所描述的语义问题的更多信息,请参阅oleb.net/blog/2016/12/protocols-have-semantics
  • @RobNapier 感谢您提供的信息,我没有意识到RangeReplaceableCollection 有一个init :) 但是,这确实比自定义协议构成了更严格的类型限制。您能否详细说明“Initializable 没有告诉您任何有关结果集合的信息(它甚至可能无效)。”?我不确定具有不带参数的 init 的集合类型如何无效?
  • 重点是Initializable 中的任何内容都没有保证结果是有用或有效的值(这与协议不需要的“集合”无关)。它只是说“它有一个 init()”。例如,NSError 有一个 init(),但结果值无效。当然也不能保证生成的集合是空的。这种特殊情况也很奇怪,因为它不需要可变性,所以我不确定它是如何工作的。
  • @RobNapier 通常你对Initializable 是正确的,但是由于这里的类型约束是Collection &amp;&amp; Initializable,我看不到如何初始化无效值的问题。由于Collection 符合类型需要扩展为也符合Initializable,OP 可以确保只有init 保证空集合的类型才能得到扩展,但我确实明白你的观点,它需要开发人员进一步关注,编译器无法为您提供所需的所有语义保证。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-05
  • 1970-01-01
相关资源
最近更新 更多