我如何" generify" Swift中的闭包类型别名?

时间:2014-09-18 10:10:43

标签: ios syntax swift closures

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

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

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

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

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

2 个答案:

答案 0 :(得分:11)

不,目前无法实现。如果 可能,那么您期望的语法是:

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

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

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

func foo(onError: FailureClosure)

使用:

func foo(onError: NSError? -> Void)

要保存几个字符,您可以强制调用者猜出FailureClosure通过的内容。 errorprogress标记对您没有帮助(您仍然需要使用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)

答案 1 :(得分:0)

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

您可能必须使用以下声明:

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