如何在Swift中“生成”闭包类型别名?

为了使我的代码更容易阅读,我在Swift中使用类型别名用于各种类型的闭包。 我有以下基本的闭包:

public typealias FailureClosure = (error: NSError?) -> Void public typealias ProgressClosure = (progress: Float32) -> Void public typealias BasicClosure = () -> Void 

我想添加一个支持generics数组的闭包typealias ,但我似乎无法弄清楚它的语法。 这是我能够得到的,但我得到编译时错误“ 使用未声明的类型’T’

 public typealias ArrayClosure = (array:[T]?) -> Void 

有人知道怎么做这个吗? 或者即使有可能吗?

不,这目前不可行。 如果可能的话,你期望的语法是:

 public typealias ArrayClosure = (array:[T]?) -> Void 

然后你会像ArrayClosure一样使用它。 但它目前不合法。

也就是说,我不推荐这些类型的别名。 它们比它们照亮的模糊不清。 比较这个签名:

 func foo(onError: FailureClosure) 

有:

 func foo(onError: NSError? -> Void) 

要保存几个字符,可以强制调用者猜出FailureClosure传递的内容。 errorprogress标记对您没有实际帮助(您仍然需要progress in ...使用progress in ... )。

一个很有意义的案例是围绕progress ,但我认为你想要的类型是:

 public typealias Progress = Float32 

这里不要误解我,在创建新类型时输入别名会非常有用。 Progress是一种碰巧实现为float的类型。 但是你正在做的很多事情(绝对使用ArrayClosure ,在较小程度上与其他人一起)只是在不创建新类型的情况下创建新语法,这通常会让人感到困惑而不是有用。


要调用您的特定示例,以及为什么过度使用类型别名会导致您使设计过于复杂:

 func foo(failure: ((error: NSError?) -> ())? = nil) 

你是对的,这真的很复杂。 比较:

 func foo(failure: NSError -> Void = {_ in return}) 

这里有两大变化。 没有理由有一个带有可选错误的故障块。 总是传递一个错误(如果没有错误,为什么会failure ?)。 并且没有理由将故障块作为可选。 如果您确实需要默认值,只需使默认值不执行任何操作。 两个选项消失了,所有消费和实现代码变得更简单。 始终要仔细考虑是否绝对必须是可选的。 可选项增加了很多复杂性; 不要轻易添加它们。

就个人而言,我可能会在很多情况下使用重载执行此操作:

 func foo(#failure: NSError -> Void) { ... } func foo() { foo(failure:{ _ in return }) } 

我只是觉得理解发生的事情要容易一些。 但无论哪种方式都没问题。


编辑(2014年12月):在写了几个月的Swift之后,我在下面的评论中更加喜欢@David的方法,即使用一个可选的闭包,但不是错误。 特别是在Swift的可选链接语法( failure?() )的情况下,它通常会更清晰。

 func foo(failure: (NSError -> Void)? = nil) 

Swift 4.1支持generics类别别名。 您可以使用此function为具有通用参数的函数提供名称。

您可能必须使用此类声明:

 public typealias ArrayClosure = ([T]?) -> Void