Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 在不知道具体类型的情况下实例化集合_Swift_Generics_Collections - Fatal编程技术网

Swift 在不知道具体类型的情况下实例化集合

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,因此不

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

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
保证集合为空的类型才能得到扩展,但我确实明白您的观点,这需要开发人员进一步注意,编译器无法为您提供所需的所有语义保证。我很好奇这解决了什么问题。如果
集合
不关心它是有序的还是唯一的,也不关心元素类型是什么,那么您会如何处理它呢