Ras*_*sto 5 types casting tuples type-conversion swift
我实际上正在做的事情更复杂,但归根结底是能够实现函数来检测某事物是一个元组,无论其元素的类型是什么。
这是我的方法,不起作用(请参阅最后一行的评论):
func isTuple(b: Any) -> Bool {
return b is (Any, Any)
}
let myString = "aa"
let myDouble = 1.2
isTuple((myString, myDouble)) //returns false
Run Code Online (Sandbox Code Playgroud)
为什么不起作用?不应该Any
也充当元组中的“通配符”吗?这是一个已知的 Swift 错误吗(如果不是,我应该将其视为一个错误并报告)吗?还有其他方法可以使isTupple
方法发挥作用吗?
@NateCook 的答案完全回答了原来的问题,但它是否并不能帮助我做我想做的事情。就是这个:
我不仅需要确定某个东西是一个元组,而且还需要将其分解为两个值,而不知道这些值的确切类型。
这是代码:
func processIfTuple(b: Any) {
if reflect(b).disposition == MirrorDisposition.Tuple {
let (first, second) = b as (Any, Any) //error when casting
process(first)
process(second)
}
}
func process(value: Any) {
...
}
processIfTuple(("aa", 1.2))
Run Code Online (Sandbox Code Playgroud)
由于测试不起作用的类似原因,这b is (Any, Any)
不起作用。这次尝试投射时出现错误。这个问题能解决吗?如果不是,是否应该将其视为语言错误或缺少功能并报告?它肯定会导致大量代码重复,因为我需要测试元组的所有可能的类型对。
您可以使用 Swift 的婴儿内省方法来实现这一点:
func isTuple(b: Any) -> Bool {
return reflect(b).disposition == MirrorDisposition.Tuple
}
Run Code Online (Sandbox Code Playgroud)
请注意,这reflect
很大程度上没有记录,可能仅作为对游乐场/调试器的支持,但据我所知,这是执行此操作的唯一方法。
为了实现这一点,您需要深入研究reflect()
给您带来的东西,这是一个符合 的结构MirrorType
,我将其称为反射,因为缺乏更好的术语。您可以为元组的反射添加下标以获取元组成员的反射,然后将值返回为Any
。此时,您可以使用可选绑定来安全地重新发现底层类型:
func process(value: Any) {
println("Any \(value)")
}
func process(value: String) {
println("String \(value)")
}
func processTuple(b: Any) -> Bool {
let isTuple = reflect(b).disposition == MirrorDisposition.Tuple
let r = reflect(b)
for i in 0..<r.count {
println(r[i].0) // string holding tuple part name: ".0", ".1", etc
println(r[i].1.value) // the value of that tuple part: "aa", 1.2
process(r[i].1.value) // calls process(Any)
if let val = r[i].1.value as? String {
process(val) // calls process(String)
}
}
return isTuple
}
let myString = "aa"
let myDouble = 1.2
processTuple((myString, myDouble)) //returns false
Run Code Online (Sandbox Code Playgroud)
输出:
.0
aa
Any aa
String aa
.1
1.2
Any 1.2
Run Code Online (Sandbox Code Playgroud)