好的,我会试着用一个最小可行的例子向你解释我想要得到的东西:我想要一个这样的结构:
struct MyStruct {
let aBool: Bool
let aInt: Int
let aHashable: Hashable?
}
但当然这是不可能的,因为:
Protocol 'Hashable' can only be used as a generic constraint because it has Self or associated type requirements
这很好。我可以通过这种方式得到我想要的:
struct MyStruct<T> where T: Hashable {
let aBool: Bool
let aInt: Int
let aHashable: T?
}
但我希望我的结构以这种方式有两个初始化:
struct MyStruct<T> where T: Hashable {
let aBool: Bool
let aInt: Int
let aHashable: T?
init(aBool: Bool, aInt: Int) {
self.init(aBool: aBool, aInt: aInt, aHashable: nil)
}
init(aHashable: T?) {
self.init(aBool: false, aInt: 0, aHashable: aHashable)
}
private init(aBool: Bool, aInt: Int, aHashable: T?) {
self.aBool = aBool
self.aInt = aInt
self.aHashable = aHashable
}
}
如果我尝试像这样初始化结构:
let myStruct = MyStruct(aBool: true, aInt: 10)
我收到一个错误:
Generic parameter 'T' could not be inferred
问题是,即使我将结构转换为非通用结构(带有几个通用初始化):
struct MyStruct {
let aBool: Bool
let aInt: Int
let aHashable: T?
init(aBool: Bool, aInt: Int) {
self.init(aBool: aBool, aInt: aInt, aHashable: nil)
}
init<T>(aHashable: T?) where T: Hashable {
self.init(aBool: false, aInt: 0, aHashable: aHashable)
}
private init<T>(aBool: Bool, aInt: Int, aHashable: T?) where T: Hashable {
self.aBool = aBool
self.aInt = aInt
self.aHashable = aHashable
}
}
我仍然收到错误消息。这次上
let aHashable: T?
存储属性:Use of undeclared type 'T'
获得我想要的东西的正确方法是什么?谢谢你。
最佳答案
T
在这种情况下,您想要的是 Never
,因为它永远不会有值。要定义这种 init,您需要将它限制在这样的扩展中:
extension MyStruct where T == Never {
init(aBool: Bool, aInt: Int) {
self.init(aBool: aBool, aInt: aInt, aHashable: nil)
}
}
IMO,Swift 也应该允许这样做:
init(aBool: Bool, aInt: Int) where T == Never {...}
但这不是目前合法的 Swift。你必须把它放在一个扩展中。这只是一个语法问题。
为了完整起见,这里是完整的代码:
struct MyStruct<T> where T: Hashable {
let aBool: Bool
let aInt: Int
let aHashable: T?
init(aHashable: T?) {
self.init(aBool: false, aInt: 0, aHashable: aHashable)
}
private init(aBool: Bool, aInt: Int, aHashable: T?) {
self.aBool = aBool
self.aInt = aInt
self.aHashable = aHashable
}
}
extension MyStruct where T == Never {
init(aBool: Bool, aInt: Int) {
self.init(aBool: aBool, aInt: aInt, aHashable: nil)
}
}
let myStruct = MyStruct(aBool: true, aInt: 10)
关于ios - Swift:非通用结构中的通用初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59291061/