Swift 在不知道具体类型的情况下实例化集合
我有一个类,它是T类型上的泛型,符合收集协议。现在我想在不知道集合的具体类型的情况下实例化集合,这可能吗Swift 在不知道具体类型的情况下实例化集合,swift,generics,collections,Swift,Generics,Collections,我有一个类,它是T类型上的泛型,符合收集协议。现在我想在不知道集合的具体类型的情况下实例化集合,这可能吗 class FileStore<T: Collection>{ var collection: T init(){ collection = T() // This will never work } } 类文件存储{ 变量集合:T init(){ collection=T()//这永远不会起作用 } } 集合的协议要求中没有init,因此不
class FileStore<T: Collection>{
var collection: T
init(){
collection = T() // This will never work
}
}
类文件存储{
变量集合:T
init(){
collection=T()//这永远不会起作用
}
}
集合
的协议要求中没有init
,因此不能直接初始化集合
实例。不过,您有几种解决方案。您可以将泛型类型约束限制为保证具有init的类型(例如数组
),也可以创建自己的协议,要求init
,使T
要求符合该协议,并扩展您希望能够存储的所有集合
以符合您的协议
第二种方法如下所示:
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>>()
Collection
的协议要求中没有init
,因此不能直接初始化Collection
实例。不过,您有几种解决方案。您可以将泛型类型约束限制为保证具有init的类型(例如数组
),也可以创建自己的协议,要求init
,使T
要求符合该协议,并扩展您希望能够存储的所有集合
以符合您的协议
第二种方法如下所示:
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>>()
我建议
T:rangereplacablecollection
而不是T:Initializable
。它提供了相同的好处,但具有适当的语义,并且碰巧是内置的。“Initializable”不会告诉您任何关于结果集合的信息(它甚至可能无效)。RangeReplaceableCollection要求生成的集合为空。为了包含Set
,您还需要提供:SetAlgebra
的版本,该版本提供相同的“init promissions empty”语义。有关我所描述的语义问题的更多信息,请参阅@RobNapier谢谢您提供的信息,我没有意识到rangereplacablecollection
有一个init
:)但是,这确实比自定义协议构成了更严格的类型限制。请您详细说明一下“Initializable不会告诉您任何有关结果集合的信息(它甚至可能无效)。”?我不确定一个具有init且没有参数的集合类型怎么可能无效?问题是,Initializable
中的任何内容都不能保证结果是有用或有效的值(这与协议不要求的“集合”无关)。它只是说“它有一个init()”。例如,NSError
有一个init()
,但结果值无效。当然也不能保证最终的集合是空的。这种特殊情况也很奇怪,因为它不需要可变性,所以我不确定它是如何工作的。@RobNapier一般来说,关于可初始化的,你是对的,但是因为这里的类型约束是集合和可初始化的,所以我看不到如何初始化无效值的问题。由于集合
一致的类型需要扩展以也符合可初始化
,OP可以确保只有init
保证集合为空的类型才能得到扩展,但我确实明白您的观点,这需要开发人员进一步注意,编译器无法为您提供所需的所有语义保证。与其T:Initializable
,我建议T:rangereplacablecollection
。它提供了相同的好处,但具有适当的语义,并且碰巧是内置的。“Initializable”不会告诉您任何关于结果集合的信息(它甚至可能无效)。RangeReplaceableCollection要求生成的集合为空。为了包含Set
,您还需要提供:SetAlgebra
的版本,该版本提供相同的“init promissions empty”语义。有关我所描述的语义问题的更多信息,请参阅@RobNapier谢谢您提供的信息,我没有意识到rangereplacablecollection
有一个init
:)但是,这确实比自定义协议构成了更严格的类型限制。请您详细说明一下“Initializable不会告诉您任何有关结果集合的信息(它甚至可能无效)。”?我不确定一个具有init且没有参数的集合类型怎么可能无效?问题是,Initializable
中的任何内容都不能保证结果是有用或有效的值(这与协议不要求的“集合”无关)。它只是说“它有一个init()”。例如,NSError
有一个init()
,但结果值无效。当然也不能保证最终的集合是空的。这种特殊情况也很奇怪,因为它不需要可变性,所以我不确定它是如何工作的。@RobNapier一般来说,关于可初始化的,你是对的,但是因为这里的类型约束是集合和可初始化的,所以我看不到如何初始化无效值的问题。由于集合
一致的类型需要扩展以也符合可初始化
,OP可以确保只有init
保证集合为空的类型才能得到扩展,但我确实明白您的观点,这需要开发人员进一步注意,编译器无法为您提供所需的所有语义保证。我很好奇这解决了什么问题。如果集合
不关心它是有序的还是唯一的,也不关心元素类型是什么,那么您会如何处理它呢