swift闭包不能覆盖Any

时间:2016-02-29 10:46:04

标签: ios swift closures

也许这是一个愚蠢的问题,但我还没有找到任何解决方案。所以,我的问题是,它有一个事件发射器协议,其功能如下:

mutating func on(eventName:String, action:((Any?)->())) {
    //..
}

我想用它来通知一些事件被一些信息触发时听众。 "登录"的访问令牌例如。

appSessionHadler.on("login") { (weak data: String?) in
    //...
}

而且我得到一个错误,我无法调用" on"使用该参数列表的类型。当然它适用于Any:

appSessionHadler.on("login") { (weak data: Any?) in
    //...
}

一切都符合任何,所以我很困惑。请有人解释一下这个!

我可以使用通用协议来解决这个问题,但它仍然让我感到沮丧,因为它不能像这样工作。

1 个答案:

答案 0 :(得分:2)

您正在做出编译器无法保留的承诺。 on函数可以随意使用任何类型的数据调用action。但您传递的功能只接受String。如果on包含以下代码(直接或间接),系统应该做什么:

action(1)

1不是String,因此类型安全性会被破坏。编译器不能让你这样做。

考虑这一点的另一种方法是on采用F类型的函数,并且您传递F超类型而不是< F的em> subtype 。 StringAny的子类型。但是函数参数的工作顺序相反。 (String)->Void(Any)->Void的超类型。所以这与将Any类型的变量传递给需要String的函数相同。在形式上我们说函数的参数是逆变的,并且它们的返回值是协变的。您可以在Type Variance in Swift

中详细了解相关内容

正如您所怀疑的那样,仿制药是正确的答案。 Any几乎总是错误的工具。 Any?是Swift中最难处理的类型之一,所以我绝对会不惜一切代价避免使用它。 (Optional本身就是Any的子类型,而Swift会自动升级到Optional,所以当你Any?开始获得双重选项时更加常见。 )