不同于大部分的编程语言,Swift中函数(Function)不仅允许重载(Overload),而且是由函数名称(Function Name)、参数标签(Argument Label)、参数类型(Parameter Type)和返回值类型(Return Type)共同确定的。比如——
func f() {}
func f() -> Int { return 0 }
func f() -> String { return "" }
func f(_ a: Int) {}
func f(_ a: String) {}
func f(a: Int) {}
func f(a: String) {}
全都可以同时存在。
在使用时,除了通常所需的函数名称和参数列表之外,有时还需要额外指定返回值类型才能避免歧义。在上述函数定义之后,单独使用——
f()
是无法通过编译的(因为f()有多种返回值类型的版本),而是需要使用——
f() as Void
let _: Void = f()
f() as Int
let _: Int = f()
f() as String
let _: String = f()
来进行区分。
所有的函数都可以使用闭包来进行引用。如果一个函数没有被重载,那么使用它的名字就能生成一个闭包,例如——
func g(b: Bool) -> Bool {
return !b
}
let g0 = g
g(b: false) == true
g(b: true) == false
g0(false) == true
g0(true) == false
其中g0的类型为(Bool) -> Bool。需要注意的是,使用g的时候并没有加上后续的括号对,这与正常的函数调用有所区别。同时,由于g0是一个闭包,调用时不再使用参数标签。
当函数被重载时,我们可能需要在指定函数名称之外指定参数标签、参数类型和/或返回值类型才能引用相应的函数。其中参数类型和返回值由闭包类型指定,而参数标签跟随函数名称进行指定。例如——
let f0 = f as () -> Void
let f1 = f as () -> Int
let f2 = f as () -> String
let f3 = f(_:) as (Int) -> Void
let f4 = f(_:) as (String) -> Void
let f5 = f(a:) as (Int) -> Void
let f6 = f(a:) as (String) -> Void
如果闭包类型部分(参数类型+返回值类型)没有歧义,则可以将其省略。
方法(Method)是特殊的函数,其也可被引用为闭包。例如——
struct S {
static func h() {}
func h() {}
}
let s = S()
let h0 = S.h
let h1 = s.h
let h2 = S.h(s)
其中h0引用了静态方法S.h(),h1和h2引用了实例方法s.h()。值得一提的是,生成h2时存在签名为static func h(_ self: S) -> () -> Void的方法S.h(s),但是实际上并不能通过S.h(_:)来引用这个方法。