我有这个问题,除了Swift.如何Type在泛型中使用变量?
我试过这个:
func intType() -> Int.Type {
return Int.self
}
func test() {
var t = self.intType()
var arr = Array<t>() // Error: "'t' is not a type". Uh... yeah, it is.
}
Run Code Online (Sandbox Code Playgroud)
这也不起作用:
var arr = Array<t.Type>() // Error: "'t' is not a type"
var arr = Array<t.self>() // Swift doesn't seem to even understand this syntax at all.
Run Code Online (Sandbox Code Playgroud)
有没有办法做到这一点?我觉得Swift不支持它并且给我一些含糊不清的错误信息.
编辑:这是一个更复杂的例子,使用通用函数头无法规避问题.当然它没有意义,但我在我的代码中的某个地方明智地使用了这种功能,而宁愿发布一个干净的例子而不是我的实际代码:
func someTypes() -> [Any.Type] {
var ret = [Any.Type]()
for (var i = 0; i<rand()%10; i++) {
if (rand()%2 == 0){ ret.append(Int.self) }
else {ret.append(String.self) }
}
return ret
}
func test() {
var ts = self.someTypes()
for t in ts {
var arr = Array<t>()
}
}
Run Code Online (Sandbox Code Playgroud)
jtb*_*des 26
Swift的静态类型意味着必须在编译时知道变量的类型.
在泛型函数的上下文中func foo<T>() { ... },T看起来像一个变量,但它的类型实际上是在编译时基于调用函数的位置而知道的.行为Array<T>()取决于T,但此信息在编译时是已知的.
使用协议时,Swift采用动态调度,因此您可以编写Array<MyProtocol>(),并且数组只是存储对实现的内容的引用MyProtocol- 因此当您从数组中获取某些内容时,您可以访问所需的所有函数/变量/类型MyProtocol.
但是,如果t实际上是一个类型的变量Any.Type,Array<t>()则没有意义,因为它的类型在编译时实际上是未知的.(由于它Array是一个通用结构,编译器需要知道哪个类型用作泛型参数,但这是不可能的.)
我建议今年观看WWDC的一些视频:
我发现这张幻灯片特别有助于理解协议和动态调度:

有一种方法,它被称为泛型.你可以做那样的事情.
class func foo() {
test(Int.self)
}
class func test<T>(t: T.Type) {
var arr = Array<T>()
}
Run Code Online (Sandbox Code Playgroud)
您将需要以某种方式提示您想要专门化该函数的类型的编译器.另一种方法是使用return param(在这种情况下被丢弃):
class func foo() {
let _:Int = test()
}
class func test<T>() -> T {
var arr = Array<T>()
}
Run Code Online (Sandbox Code Playgroud)
在类(或结构)上使用泛型,您不需要额外的参数:
class Whatever<T> {
var array = [T]() // another way to init the array.
}
let we = Whatever<Int>()
Run Code Online (Sandbox Code Playgroud)
jtbandes 的回答 - 您不能使用当前的方法,因为 Swift 是静态类型的 - 是正确的。
但是,如果您愿意在数组中创建允许类型的白名单,例如在 中enum,您可以在运行时动态初始化不同的类型。
首先,创建一个enum允许的类型:
enum Types {
case Int
case String
}
Run Code Online (Sandbox Code Playgroud)
创建一个Example类。实现您的someTypes()函数以使用这些枚举值。(您可以轻松地将字符串的 JSON 数组转换为该枚举的数组。)
class Example {
func someTypes() -> [Types] {
var ret = [Types]()
for _ in 1...rand()%10 {
if (rand()%2 == 0){ ret.append(.Int) }
else {ret.append(.String) }
}
return ret
}
Run Code Online (Sandbox Code Playgroud)
现在实现您的测试功能,使用switch来arr限定每个允许的类型:
func test() {
let types = self.someTypes()
for type in types {
switch type {
case .Int:
var arr = [Int]()
arr += [4]
case .String:
var arr = [String]()
arr += ["hi"]
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
您可能知道,您也可以声明arr为[Any]混合类型(jtbandes 回答中的“异构”情况):
var arr = [Any]()
for type in types {
switch type {
case .Int:
arr += [4]
case .String:
arr += ["hi"]
}
}
print(arr)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
21357 次 |
| 最近记录: |