微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

类型转换/多态如何在Swift中使用这种嵌套的闭包类型?

我知道(Int) – > Void不能被特定为(任何) – >无效:
let intHandler: (Int) -> Void = { i in
    print(i)
}
var anyHandler: (Any) -> Void = intHandler <<<< ERROR

这给出了:

error: cannot convert value of type ‘(Int) -> Void’ to specified type
‘(Any) -> Void’

问:但我不知道为什么这个工作?

let intResolver: ((Int) -> Void) -> Void = { f in
    f(5)
}

let stringResolver: ((String) -> Void) -> Void = { f in
    f("wth")
}

var anyResolver: ((Any) -> Void) -> Void = intResolver

我弄乱了返回类型,它仍然可以工作……:

let intResolver: ((Int) -> Void) -> String = { f in
    f(5)
    return "I want to return some string here."
}

let stringResolver: ((String) -> Void) -> Void = { f in
    f("wth")
}

var anyResolver: ((Any) -> Void) -> Any = intResolver (or stringResolver)

对不起,如果以前询问过.我还没有找到这样的问题,也许我不知道这里的关键字.
请赐教!

如果你想尝试:https://iswift.org/playground?wZgwi3&v=3

这完全是关于 variance和Swift的关闭.

Swift在闭包返回类型方面是协变的,在其参数方面是反变量.这使得具有相同返回类型或更具体的闭包,以及相同的参数或更不具体的闭包是兼容的.

因此(Arg1) – >可以将Res1分配给(Arg2) – > Res2如果Res1:Res2和Arg2:Arg1.

为了表达这一点,让我们稍微调整一下第一个闭包:

import Foundation

let nsErrorHandler: (customstringconvertible) -> NSError = { _ in
    return NSError(domain: "",code: 0,userInfo: nil)
}
var anyHandler: (Int) -> Error = nsErrorHandler

上面的代码有效,因为Int符合customstringconvertible,而NSError符合Error.任何人都会工作而不是错误,因为它更通用.

现在我们建立了这个,让我们看看你的两个代码块中会发生什么.

一个块尝试将一个更具体的参数闭包分配给一个不太具体的参数闭包,这不遵循方差规则,因此它不会编译.

第二块代码怎么样?我们处于与第一个块类似的场景:具有一个参数的闭包.

>我们知道String或Void比Any更具体,所以我们可以将它用作返回值
>(Int) – > Void比(Any)更具体 – > Void(闭包方差规则),因此我们可以将它用作参数

闭合方差得到遵守,因此intResolver和stringResolver是anyResolver的兼容匹配.这听起来有点违反直觉,但仍然遵循编译规则,这允许分配.

事情变得复杂但是如果我们想要使用闭包作为通用参数,则方差规则不再适用,并且这是由于Swift泛型(具有少数例外)在其类型方面是不变的:MyGenericType< B>无法分配给MyGenericType< A>即使B:A.例外是标准库结构,如Optional和Array.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐