Using a Type Variable in a Generic
我有这个问题,除了斯威夫特。如何在泛型中使用
我试过这个:
1 2 3 4 5 6 7 8 | 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. } |
这也不起作用:
1 2 | 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. |
有办法吗?我有种感觉,斯威夫特只是不支持它,并给了我一些模棱两可的错误信息。
编辑:这里有一个更复杂的例子,在这个例子中,不能使用通用函数头来规避问题。当然,这是没有意义的,但是我在代码的某个地方对这种功能有了合理的使用,我宁愿发布一个干净的示例而不是实际的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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>() } } |
swift的静态类型意味着在编译时必须知道变量的类型。
在泛型函数
在使用协议时,swift采用动态调度,因此您可以编写
但是如果
我建议今年观看世界野生动物保护协会的一些视频:
- SWIFT中面向协议的程序设计
- 在Swift中构建具有价值类型的更好的应用程序
我发现这张幻灯片对于理解协议和动态调度特别有用:
有一种方法叫仿制药。你可以这样做。
1 2 3 4 5 6 7 | class func foo() { test(Int.self) } class func test<T>(t: T.Type) { var arr = Array<T>() } |
您将需要提示编译器您希望用某种方式专门化函数的类型。另一种方法是使用返回参数(在这种情况下丢弃):
1 2 3 4 5 6 7 | class func foo() { let _:Int = test() } class func test<T>() -> T { var arr = Array<T>() } |
在类(或结构)上使用泛型,不需要额外的参数:
1 2 3 4 5 | class Whatever<T> { var array = [T]() // another way to init the array. } let we = Whatever<Int>() |
jtbandes的答案是正确的,因为Swift是静态类型,所以您不能使用当前的方法。
但是,如果您愿意在数组中创建允许类型的白名单,例如在
首先,创建一个允许类型的
1 2 3 4 | enum Types { case Int case String } |
创建一个
1 2 3 4 5 6 7 8 9 | 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 } |
现在,使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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"] } } } } |
如您所知,您也可以将
1 2 3 4 5 6 7 8 9 10 11 12 13 | var arr = [Any]() for type in types { switch type { case .Int: arr += [4] case .String: arr += ["hi"] } } print(arr) |
我会用你从第一个答案中学到的东西来分解它。我冒昧地重构了一些代码。这里是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | func someTypes<T>(t: T.Type) -> [Any.Type] { var ret = [Any.Type]() for _ in 0..<rand()%10 { if (rand()%2 == 0){ ret.append(T.self) } else { ret.append(String.self) } } return ret } func makeArray<T>(t: T) -> [T] { return [T]() } func test() { let ts = someTypes(Int.self) for t in ts { print(t) } } |
这有点奏效,但我相信这样做的方式非常不正统。你能用反射(镜像)代替吗?