位置:首頁 > 高級語言 > Swift教學 > Swift函數類型

Swift函數類型

函數類型(Function Types)

每個函數都有種特定的函數類型,由函數的參數類型和返回類型組成。

例如:

func addTwoInts(a: Int, b: Int) -> Int {
    return a + b
}
func multiplyTwoInts(a: Int, b: Int) -> Int {
    return a * b
}

這個例子中定義了兩個簡單的數學函數:addTwoInts 和 multiplyTwoInts。這兩個函數都傳入兩個 Int 類型, 返回一個合適的Int值。

這兩個函數的類型是 (Int, Int) -> Int,可以讀作“這個函數類型,它有兩個 Int 型的參數並返回一個 Int 型的值。”。

下麵是另一個例子,一個冇有參數,也冇有返回值的函數:

func printHelloWorld() {
    println("hello, world")
}

這個函數的類型是:() -> (),或者叫“冇有參數,並返回 Void 類型的函數”。冇有指定返回類型的函數總返回Void。在Swift中,Void 與空的元組是一樣的。

使用函數類型(Using Function Types)

在 Swift 中,使用函數類型就像使用其他類型一樣。例如,你可以定義一個類型為函數的常量或變量,並將函數賦值給它:

var mathFunction: (Int, Int) -> Int = addTwoInts

這個可以讀作:

“定義一個叫做 mathFunction 的變量,類型是‘一個有兩個 Int 型的參數並返回一個 Int 型的值的函數’,並讓這個新變量指向 addTwoInts 函數”。

addTwoInts 和 mathFunction 有同樣的類型,所以這個賦值過程在 Swift 類型檢查中是允許的。

現在,你可以用 mathFunction 來調用被賦值的函數了:

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”

這個例子定義了 printMathResult 函數,它有三個參數:第一個參數叫 mathFunction,類型是(Int, Int) -> Int,你可以傳入任何這種類型的函數;第二個和第三個參數叫 a 和 b,它們的類型都是 Int,這兩個值作為已給的函數的輸入值。

當 printMathResult 被調用時,它被傳入 addTwoInts 函數和整數35。它用傳入35調用 addTwoInts,並輸出結果:8

printMathResult 函數的作用就是輸出另一個合適類型的數學函數的調用結果。它不關心傳入函數是如何實現的,它隻關心這個傳入的函數類型是正確的。這使得 printMathResult 可以以一種類型安全(type-safe)的方式來保證傳入函數的調用是正確的。

函數類型作為返回類型(Function Type as Return Types)

你可以用函數類型作為另一個函數的返回類型。你需要做的是在返回箭頭(->)後寫一個完整的函數類型。

下麵的這個例子中定義了兩個簡單函數,分彆是 stepForward 和stepBackwardstepForward 函數返回一個比輸入值大一的值。stepBackward 函數返回一個比輸入值小一的值。這兩個函數的類型都是 (Int) -> Int

func stepForward(input: Int) -> Int {
    return input + 1
}
func stepBackward(input: Int) -> Int {
    return input - 1
}

下麵這個叫做 chooseStepFunction 的函數,它的返回類型是 (Int) -> Int 的函數。chooseStepFunction 根據布爾值 backwards 來返回 stepForward 函數或 stepBackward 函數:

func chooseStepFunction(backwards: Bool) -> (Int) -> Int {
    return backwards ? stepBackward : stepForward
}

你現在可以用 chooseStepFunction 來獲得一個函數,不管是那個方向:

var currentValue = 3
let moveNearerToZero = chooseStepFunction(currentValue > 0)
// moveNearerToZero now refers to the stepBackward() function

上麵這個例子中計算出從 currentValue 逐漸接近到0是需要向正數走還是向負數走。currentValue 的初始值是3,這意味著 currentValue > 0 是真的(true),這將使得 chooseStepFunction 返回 stepBackward 函數。一個指向返回的函數的引用保存在了 moveNearerToZero 常量中。

現在,moveNearerToZero 指向了正確的函數,它可以被用來數到0

println("Counting to zero:")
// Counting to zero:
while currentValue != 0 {
    println("\(currentValue)... ")
    currentValue = moveNearerToZero(currentValue)
}
println("zero!")
// 3...
// 2...
// 1...
// zero!