Swift 泛型结构的集合
我在Swift中遇到了一些泛型问题。我有一个通用结构:Swift 泛型结构的集合,swift,generics,collections,struct,Swift,Generics,Collections,Struct,我在Swift中遇到了一些泛型问题。我有一个通用结构: struct MyStruct<T> { ... } 您会注意到我没有为MyStruct指定t的类型。这是因为我想存储任何MyStruct,独立于类型T 好吧,你说,用Any表示T([MyKeyType:MyStruct])。是的,但是当我从字典中获取结构时,我想也想保留每个结构的T的原始类型信息,这样当调用一个采用MyStruct的函数时,它就会被正确的T类型调用 下面是一个例子: // Setup var myStruct
struct MyStruct<T> { ... }
您会注意到我没有为MyStruct
指定t
的类型。这是因为我想存储任何MyStruct
,独立于类型T
好吧,你说,用Any
表示T
([MyKeyType:MyStruct]
)。是的,但是当我从字典中获取结构时,我想也想保留每个结构的T
的原始类型信息,这样当调用一个采用MyStruct
的函数时,它就会被正确的T
类型调用
下面是一个例子:
// Setup
var myStructDict: [String: MyStruct<Any>]
func f(v: MyStruct<String>) { ... }
func f(v: MyStruct<Int>) { ... }
// Set value
let s1 = MyStruct<String>(...)
myStructDict["key"] = unsafeTypeCast(s, MyStruct<Any>.self)
// Get value
let s2 = myStructDict["key"]
// Call function
f(s2) // I want the function that takes a `MyStruct<String>` to be called
但这根本不是一个好主意,因为
Any
,嗯…,是任何类型。泛型类型在Swift中并不统一MyStruct
和MyStruct
是完全不同的类型,就像Int
和String
一样,无论它们看起来有多相似。这是类型保留泛型系统的属性之一(与Java中的类型擦除泛型系统相反)
不同类型的泛型系统可以用于不同的事情。当您开始专门化并以自己的方式编写更通用的代码时,类型保留泛型是最好的,即编写符合协议的特定类型,然后编写使用这些协议的泛型函数或类型,或者使用泛型创建可以包含其他类型值的包装类型,而不考虑这些类型是什么
另一方面,您需要从泛型类型返回到内部的专用类型,或者尝试创建相关泛型类型的泛化的用例可能不那么简单
您要查找的内容需要两个部分:
MyStruct
和MyStruct
具有公共类型祖先的方法,因此可以将所述类型声明为字典中的元素类型MyStruct
的特殊类型进行分派的一种方法[MyKeyType:MyStruct]
创建字典,为[MyKeyType:MyValueType]
创建字典,其中MyValueType
是MyStruct
和MyStruct
都遵守的协议。(你可以使用Any
作为你的值类型,但是你的字典里会有一些东西不是MyStruct
s)例如:
protocol MyType {
func doNothing()
}
struct MyStruct<T>: MyType {
let thing: T
func doNothing() {}
}
let a = MyStruct(thing: "Hello")
let b = MyStruct(thing: 1)
let dict: [String: MyType] = ["a": a, "b": b]
默认情况下,您的“担保”起作用。就语言而言,无法使此开关
详尽无遗,因此您需要进行运行时测试,以确保您没有尝试调用超出您所定义类型的f
因此,事实上,您对需要
开关的猜测是正确的。但这是一个好主意,因为它(或类似的东西)是消除泛型类型歧义的唯一方法。您至少可以将其限制为需要处理您的MyType
协议,而不是Any
。unsafeTypeCast
是。。。嗯,不安全,所以我建议不要使用它作为构建类型层次结构的基础,你可以对此进行推理。@rickster AFAIK,unsafeTypeCast
是不安全的,因为你可能会执行unsafeTypeCast(myProbablyAnInt,Int.self)
,如果结果是myProbablyAnInt
是一个字符串
,那么,然后程序崩溃了。我在这里以一种非不安全的方式使用它(我认为),只是为了避开自定义类型使用Swift的事实:我不能在需要使用MyStruct
的地方给出MyStruct
。感谢您的详细解释和有趣的建议。我将在我的代码中试用它们,看看它们是否符合我的要求。
switch s1 {
case let v as MyStruct<String>: f(v)
...
}
protocol MyType {
func doNothing()
}
struct MyStruct<T>: MyType {
let thing: T
func doNothing() {}
}
let a = MyStruct(thing: "Hello")
let b = MyStruct(thing: 1)
let dict: [String: MyType] = ["a": a, "b": b]
func f(v: MyStruct<String>) { print("String \(v)") }
func f(v: MyStruct<Int>) { print("Int \(v)") }
func f(v: MyType) {
switch v {
case let str as MyStruct<String>:
f(str)
case let num as MyStruct<Int>:
f(num)
default:
fatalError("unsupported type")
break
}
}