函数类型(Function Types)
每个函数都有种特定的函数类型,由函数的参数类型和返回类型组成。
例如:
func addTwoInts(a: Int, b: Int) -> Int {
return a + b
}
func multiplyTwoInts(a: Int, b: Int) -> Int {
return a * b
}
这个例子中定义了两个简单的数学函数:addTwoInts
%uA0和%uA0multiplyTwoInts
。这两个函数都传入两个%uA0Int
%uA0类型, 返回一个合适的Int
值。
这两个函数的类型是%uA0(Int, Int) -> Int
,可以读作“这个函数类型,它有两个%uA0Int
%uA0型的参数并返回一个%uA0Int
%uA0型的值。”。
下面是另一个例子,一个没有参数,也没有返回值的函数:
func printHelloWorld() {
println("hello, world")
}
这个函数的类型是:() -> ()
,或者叫“没有参数,并返回%uA0Void
%uA0类型的函数”。没有指定返回类型的函数总返回Void
。在Swift中,Void
%uA0与空的元组是一样的。
使用函数类型(Using Function Types)
在 Swift 中,使用函数类型就像使用其他类型一样。例如,你可以定义一个类型为函数的常量或变量,并将函数赋值给它:
var mathFunction: (Int, Int) -> Int = addTwoInts
这个可以读作:
“定义一个叫做%uA0mathFunction
%uA0的变量,类型是‘一个有两个%uA0Int
%uA0型的参数并返回一个%uA0Int
%uA0型的值的函数’,并让这个新变量指向%uA0addTwoInts
%uA0函数”。
addTwoInts
%uA0和%uA0mathFunction
%uA0有同样的类型,所以这个赋值过程在 Swift 类型检查中是允许的。
现在,你可以用%uA0mathFunction
%uA0来调用被赋值的函数了:
println("Result: \(mathFunction(2, 3))")
// prints "Result: 5"
有相同匹配类型的不同函数可以被赋值给同一个变量,就像非函数类型的变量一样:
mathFunction = multiplyTwoInts
println("Result: \(mathFunction(2, 3))")
// prints "Result: 6"
就像其他类型一样,当赋值一个函数给常量或变量时,你可以让 Swift 来推断其函数类型:
let anotherMathFunction = addTwoInts
// anotherMathFunction is inferred to be of type (Int, Int) -> Int
函数类型作为参数类型(Function Types as Parameter Types)
你可以用(Int, Int) -> Int
这样的函数类型作为另一个函数的参数类型。这样你可以将函数的一部分实现交由给函数的调用者。
下面是另一个例子,正如上面的函数一样,同样是输出某种数学运算结果:
func printMathResult(mathFunction: (Int, Int) -> Int, a: Int, b: Int) {
println("Result: \(mathFunction(a, b))")
}
printMathResult(addTwoInts, 3, 5)
// prints "Result: 8”
这个例子定义了%uA0printMathResult
%uA0函数,它有三个参数:第一个参数叫%uA0mathFunction
,类型是(Int, Int) -> Int
,你可以传入任何这种类型的函数;第二个和第三个参数叫%uA0a
%uA0和%uA0b
,它们的类型都是%uA0Int
,这两个值作为已给的函数的输入值。
当%uA0printMathResult
%uA0被调用时,它被传入%uA0addTwoInts
%uA0函数和整数3
和5
。它用传入3
和5
调用%uA0addTwoInts
,并输出结果:8
。
printMathResult
%uA0函数的作用就是输出另一个合适类型的数学函数的调用结果。它不关心传入函数是如何实现的,它只关心这个传入的函数类型是正确的。这使得%uA0printMathResult
%uA0可以以一种类型安全(type-safe)的方式来保证传入函数的调用是正确的。
函数类型作为返回类型(Function Type as Return Types)
你可以用函数类型作为另一个函数的返回类型。你需要做的是在返回箭头(->
)后写一个完整的函数类型。
下面的这个例子中定义了两个简单函数,分别是%uA0stepForward
%uA0和stepBackward
。stepForward
%uA0函数返回一个比输入值大一的值。stepBackward
%uA0函数返回一个比输入值小一的值。这两个函数的类型都是%uA0(Int) -> Int
:
func stepForward(input: Int) -> Int {
return input + 1
}
func stepBackward(input: Int) -> Int {
return input - 1
}
下面这个叫做%uA0chooseStepFunction
%uA0的函数,它的返回类型是%uA0(Int) -> Int
%uA0的函数。chooseStepFunction
%uA0根据布尔值%uA0backwards
%uA0来返回%uA0stepForward
%uA0函数或%uA0stepBackward
%uA0函数:
func chooseStepFunction(backwards: Bool) -> (Int) -> Int {
return backwards ? stepBackward : stepForward
}
你现在可以用%uA0chooseStepFunction
%uA0来获得一个函数,不管是那个方向:
var currentValue = 3
let moveNearerToZero = chooseStepFunction(currentValue > 0)
// moveNearerToZero now refers to the stepBackward() function
上面这个例子中计算出从%uA0currentValue
%uA0逐渐接近到0
是需要向正数走还是向负数走。currentValue
%uA0的初始值是3
,这意味着%uA0currentValue > 0
%uA0是真的(true
),这将使得%uA0chooseStepFunction
%uA0返回%uA0stepBackward
%uA0函数。一个指向返回的函数的引用保存在了%uA0moveNearerToZero
%uA0常量中。
现在,moveNearerToZero
%uA0指向了正确的函数,它可以被用来数到0
:
println("Counting to zero:")
// Counting to zero:
while currentValue != 0 {
println("\(currentValue)... ")
currentValue = moveNearerToZero(currentValue)
}
println("zero!")
// 3...
// 2...
// 1...
// zero!