是否可以检查值是否动态确认通用协议?
我想做这样的事情:
import func Darwin.atoll
func anyToInt(a: Any) -> IntMax {
if let v = a as? IntegerType { // error!!
return v.toIntMax()
} else {
return atoll("\(a)")
}
}
这会使编译错误消息"错误:protocol' IntegerType'只能用作通用约束..."。
如果我使用了正确的静态类型,我会按类型参数约束使用重载:
func anyToInt<T where T: IntegerType>(a: T) -> IntMax {
return a.toIntMax()
}
func anyToInt<T>(a: T) -> IntMax {
return atoll("\(a)")
}
不幸的是,在我的情况下,没有办法使用静态类型而不是Any。
答案 0 :(得分:2)
由于以下几个原因,你不能这样做:
首先,Any
可能支持您can’t cast the contents of an Any
to a protocol。您只能获得包含的显式类型:
let i = 1
i as Printable // works
let a: Any = i
a as? Printable // doesn’t work
let p = a as Int as Printable // works
// or, if you don’t want to crash if a isn’t an Int
let p = (a as? Int).map { $0 as Printable }
// (is there a cleaner syntax than this?)
其次,您无法实例化具有关联类型的协议。您只能将它们用作通用约束。仅Printable
的示例才有效,因为它没有关联的类型。有关原因的说明,请参阅this answer。因此,即使转换Any
可以处理协议,也无法将其转换为IntegerType
。
但是你确定你必须在这里使用Any
吗?除非别无选择,否则最好避免Any
。也许你可以将泛型进一步推向管道?