如何检查 Any 值是否确认通用协议,例如整数类型

How can I check whether an Any value confirms a generic protocol, e.g. IntegerType

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

我想做这样的事情:

import func Darwin.atoll
func anyToInt(a: Any) -> IntMax {
    if let v = a as? IntegerType { // error!!
        return v.toIntMax()

    } else {
        return atoll("\(a)")
    }
}

这会导致编译错误并显示消息 "error: protocol 'IntegerType' can only be used as a generic constraint ..."。

如果我使用正确的静态类型,我会通过类型参数约束使用重载:

func anyToInt<T where T: IntegerType>(a: T) -> IntMax {
    return a.toIntMax()
}
func anyToInt<T>(a: T) -> IntMax {
    return atoll("\(a)")
}

然而不幸的是,在我的例子中没有使用静态类型而不是 Any 的方法。

你不能,有几个原因:

首先,您 can’t cast the contents of an Any to a protocol Any 可能会支持。只能取出显式包含的类型:

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 { [=10=] as Printable } 
// (is there a cleaner syntax than this?)

其次,您不能实例化具有关联类型的协议。您只能将它们用作通用约束。 Printable 的示例之所以有效,是因为它没有关联类型。有关原因的解释,请参阅 this answer。所以即使转换 Any 可以在协议上工作,你也不能将它转换为 IntegerType.

但是你确定你必须在这里使用Any吗? Any 真的最好避免,除非别无选择。也许您可以将仿制药进一步推向管道?