如何检查Any值是否确认通用协议,例如IntegerType

时间:2015-01-02 04:50:14

标签: swift

是否可以检查值是否动态确认通用协议?

我想做这样的事情:

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。

1 个答案:

答案 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。也许你可以将泛型进一步推向管道?