函数和闭包
- 基本概念
- 函数时一个独立的代码块,用来执行特定的任务,通过给函数一个名称来定义它的功能,并且在需要的 时候,通过这个名字来“调用”函数执行它的任务
- Swift 统一的函数语法时分灵活,可以表达从简单的无形参数的 C 风格函数到复杂的每一个形式参数,都带有局部和外部形式参数名的 Objective-C 风格方法的任何内容,形式参数能提供一个默认的值来简化函数的调用,也可以被当做输入输出形式参数被传递,它在函数执行完成时修改传递来的变量
- Swift 的每一个函数都有类型, 由函数的形式参数类型和返回类型组成,你可以像 Swift 中其他类型那样来使用它,这使得你能够方便的将一个函数当做一个形式参数传递到另外的一个函数中,也可以在一个函数中返回另一个函数,函数同时也可以写在其他函数内部来内嵌范围封装有用的功能
- 定义和调用函数
- 当你定义了一个函数的时候,你可以选择定义一个或者多个命令的分类的值座位函数的输入(所谓的形式参数),并且、或者定义函数完成后将要传回座位输出的值的类型(所谓他的返回类型)
- 每一个函数都有一个函数名,它描述函数执行的任务,要使用一个函数,你可以通过“调用”函数的名字,并且传入一个符合函数形式参数类型的输入值(所谓实际参数)来调用这个函数,给函数提供的实际参数的顺序必须符合函数的形式参数列表顺序
func greet(person: String) -> String {
let greeting = "Hello, " + person + "!"
return greeting
}
- 无形式参数的函数
- 函数没有要求必须输入一个参数,可以没有形式参数
- 函数的定义仍然需要在名字后边加一个圆括号,即使它不接受形式参数也得这样做。当函数被调用的时候也要在函数的名字后边加一个空圆括号
func sayHelloWorld() -> String {
return "Hello, world"
}
print(sayHelloWorld())
- 多形式参数的函数
- 函数可以输入多个形式参数,可以写在函数后边的圆括号内,用都好分隔
func greetAgain(person: String) -> String {
let greeting = "Hello again, " + person + "!"
return greeting
}
func greet(person: String) -> String {
let greeting = "Hello, " + person + "!"
return greeting
}
func greet(person: String, alreadyGreeted: Bool) -> String {
if alreadyGreeted {
return greetAgain(person: person)
} else {
return greet(person: person)
}
}
print(greet(person: "Tim", alreadyGreeted: true))
- 无返回值的函数
- 函数定义中没有要求必须有一个返回类型
- 不需要返回值,函数在定义的时候就没有包含返回箭头(->)或者返回类型
- 严格来讲,函数greet(person:)还是有一个返回值的, 尽管没有定义返回值,没有定义返回类型的函数,实际上狐疑返回一个特殊的类型 Void,它其实是一个空的元组,作用相当于没有元素的元组,可以写作()
func greet(person: String) {
print("Hello, \(person)!")
}
greet(person: "Dave")
- 多返回值的函数
- 为了让函数返回值作为一个符合的返回值,你可以使用元组类型作为返回值
func minMax(array: [Int]) -> (min: Int, max: Int) {
var currentMin = array[0]
var currentMax = array[0]
for value in array[1..<array.count] {
if value < currentMin {
currentMin = value
} else if value > currentMax {
currentMax = value
}
}
return (currentMin, currentMax)
}
let arr = [123, 42, 2, 434, 12]
print(minMax(array: arr))
- 可选元组返回类型
- 如果元组在函数中的返回类型中有可能“没有值”,你可以用一个可选元组返回类型来说明整个元组的可能是nil,写法是在可选元组类型的圆括号后面添加一个问号(?)
func minMax(array: [Int]) -> (min: Int, max: Int)? {
if array.isEmpty {
return nil
}
var currentMin = array[0]
var currentMax = array[0]
for value in array[1..<array.count] {
if value < currentMin {
currentMin = value
} else if value > currentMax {
currentMax = value
}
}
return (currentMin, currentMax)
}
if let bounds = minMax(array: [8, -6, 2, 109, 3, 71]) {
print("min is \(bounds.min) and max is \(bounds.max)")
}
- 隐式返回函数
- 如果整个函数体是一个单一表达式,那么函数隐式返回这个表达式
func greeting(for person: String) -> String {//Swift 5.1新特性 xcode11+支持
"Hello, " + person + "!"
}
print(greeting(for: "Dave"))
func anotherGreeting(for person: String) -> String {
return "Hello, " + person + "!"
}
print(anotherGreeting(for: "Dave"))
函数的形式参数和返回值
- 实参标签和形参名
- 每一个函数的形式参数都包含:实际参数标签和形式参数名,实际参数标签用在调用函数的时候,在调用函数的时候,每一个时间参数前边都要写实际参数标签,形式参数名用在函数的实现中,默认情况下,形式参数使用他们的形式参数名作为时间参数标签
- 所有的形式参数必须有唯一的名字,尽管有可能多个形式参数拥有相同的实际参数标签,唯一的实际参数标签有助于让你的代码更加易读
func someFunction(firstParmeterName: Int, secondParameterName: Int) {
}
someFunction(firstParmeterName: 1, secondParameterName: 2)
- 指定实际参数标签
- 在提供形式参数名之前写实际参数标签,用空格分隔
- 如果你为一个形式参数提供了实际参数标签,那么这个实际参数就必须在调用函数的时候使用标签
- 实际参数标签的使用能够让函数的调用更加明确,更像是自然语句,同时还能提供更刻度的函数体,并清晰的表达你的意图
func greet(person: String, from hometown: String) -> String {
return "Hello \(person)! Glad you could visit from \(hometown)"
}
print(greet(person: "Bill", from: "Cupertino"))
- 省略实际参数标签
- 如果对于函数的形式参数不想使用实际参数标签的话,可以利用下划线(_)来为这个形式参数代替显式的实际参数标签
func someFunction(_ firstParmeterName: Int, secondParameterName: Int) {
}
someFunction(1, secondParameterName: 2)
- 默认形式参数值
- 你可以通过在形式参数类型后,给形式参数赋一个值,来给函数的任意形式参数定义一个默认值
- 如果定义了默认值,你就可以在调用函数时候省略这个形式参数
func someFunction(parameterWithDefault: Int = 12) {
print(parameterWithDefault)
}
someFunction(parameterWithDefault: 6)
someFunction()
- 可变形式参数
- 一个可变形式参数可以接受零或者多个特定类型的值,当调用函数的时候,你可以利用可变形式参数来声明形式参数,可以被传入值的数量是可变的,可以通过在形式参数的类型名后面插入三个点符号(...)来书写可变形式参数
- 传入到可变参数中的值在函数的主体中杯当做是对应类型的数组
func arithmeticMean(_ numbers: Double...) -> Double {
var total: Double = 0
for number in numbers {
total += number
}
return total / Double(numbers.count)
}
print(arithmeticMean(1, 2, 3, 4, 5))
print(arithmeticMean(3, 8.25, 18.75))
- 输入输出形式参数
- 可变形式参数只能在函数内部做改变,如果你想函数能够修改一个形式参数的值,而且你想这些改变在函数结束之后依然生效,那么就需要将形式参数定义为输入输出形式参数
- 在形式参数定义开始的时候,在前面添加一个 inout 关键字,可以定义一个输入输出形式参数,输入输出形式参数有一个能输入给函数,函数能对其进行修改,还能输出到函数外边替换原来的值
- 你只能把变量座位输入输出形式参数的实际参数,再将变量座位实际参数传递给输入输出参数的时候,直接在它前面添加一个和符合(&)来明确可以被函数修改
- 输入输出形式参数不能有默认值,可变形式参数不能标记为 inout
func swapTwoInts(_ a: inout Int, _ b: inout Int) {
let temp = a
a = b
b = temp
}
var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
print("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
函数类型和内嵌函数
- 函数类型
- 每一个函数都有一个特定的类型,它由事项参数类型,返回类型组成
func addTwoInts(_ a: Int, _ b: Int) -> Int {
return a + b
}
func multiplyTwoInts(_ a: Int, _ b: Int) -> Int {
return a * b
}
//(Int, Int) -> Int
var someInt = 3
var anotherInt = 107
func swapTwoInts(_ a: inout Int, _ b: inout Int) {
let temp = a
a = b
b = temp
}
//如果没有返回值,我的函数类型要在返回箭头添加 ()
//如果是输入输出类型的, 需要在参数前面指定inout
let swapFunc: (inout Int, inout Int) -> () = swapTwoInts(_:_:)
swapFunc(&someInt, &anotherInt)
print(someInt)
print(anotherInt)
- 使用函数类型
- 你可以像使用 Swift 中的其他类型一样使用函数类型,
func addTwoInts(first a: Int, _ b: Int) -> Int {
return a + b
}
var mathFunction: (Int, Int) -> Int = addTwoInts(first:_:)
print(mathFunction(2, 3))
- 函数类型作为形式参数类型
- 你可以利用使用一个函数的类型:例如(Int, Int) ->Int 作为其他函数的形式参数类型。这允许你预留函数的部分实现,从而让函数的调用者在调用函数的时候提供
func addTwoInts(first a: Int, _ b: Int) -> Int {
return a + b
}
func printMathResult(_ mathFounction:(Int, Int) -> Int, _ a: Int, _ b: Int) {
print("Result: \(mathFounction(a, b))")
}
printMathResult(addTwoInts(first:_:), 4, 5)
- 函数类型座位返回类型
- 你可以利用函数的类型座位另一个函数的返回类型,写法是在函数的返回箭头(->)后立即写一个完整的函数类型
func stepForward(_ input: Int) -> Int {
return input + 1
}
func stepBackward(_ input: Int) -> Int {
return input - 1
}
func chooseStepFunction(backwards: Bool) -> (Int) -> Int {
return backwards ? stepBackward(_:) : stepForward(_:)
}
var currentValue = 3
let moveNearerToZero = chooseStepFunction(backwards: currentValue > 0)
print("Counting to zero:")
while currentValue != 0 {
print("\(currentValue)")
currentValue = moveNearerToZero(currentValue)
}
print("zero")
- 内嵌函数
- 可以再函数的内部定义另外一个函数,这就是内嵌函数
- 内嵌函数在默认情况下,在外部是被隐藏起来的,单却仍然可以通过包裹他们的函数来调用他们,包裹的函数也可以返回它内部的一个内嵌函数来另外的范围里使用
func chooseStepFunction(backwards: Bool) -> (Int) -> Int {
func stepForward(_ input: Int) -> Int { return input + 1 }
func stepBackward(_ input: Int) -> Int { return input - 1 }
return backwards ? stepBackward(_:) : stepForward(_:)
}
var currentValue = -4
let moveNearerToZero = chooseStepFunction(backwards: currentValue > 0)
print("Counting to zero:")
while currentValue != 0 {
print("\(currentValue)")
currentValue = moveNearerToZero(currentValue)
}
print("zero!")
func addTwoNumbers(a: Int, b: Int) -> Int {
return a + b
}
func printMathResult(_ mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) {
print(mathFunction(a, b))
}
printMathResult(addTwoNumbers(a:b:), 3, 5)
网友评论