本篇介绍Swift的基础知识:函数和闭包(Closure)。
Title: Swift基础入门(5):函数和闭包
Author: Yunyao Zhang(张云尧)
E-mail: aidaizyy@gmail.com
Last Modified: 2015-07-22
函数
函数原型
func functionName(parameters) -> returnType { statements }
函数前必须加标识符func,函数名halfOpenRangeLength需要传入两个参数start和end,都是Int类型,返回Int类型。
可以没有参数,也可以没有返回值,则写作func halfOpenRangeLength() { statements },statements中不带return语句。
函数可以有多个返回值,用元组表示返回值。
func count(String) -> (Int, Int, Int)函数,传入一个String值,返回一个带3个Int值的元组。
返回的元组成员不需要再命名,因为在函数定义时已经命名了返回元组成员的名称。
当然也可以不命名,返回类型写作(Int, Int, Int)的形式,用total.0,total.1和total.2去获取元组total的第1个,第2个和第3个成员的值。
函数参数
外部参数名
函数参数的名称作为局部参数名,只能在函数中使用。定义外部参数名,可以在函数外部使用帮助函数参数的意图清晰,func functionName(externalParameterName localParameterName: dataType) { statements }。
注意:但是一旦定义了外部参数名,在函数调用时就必须使用。
外部参数名和局部参数名如果一致,可在局部参数名前加#表示,func functionName(#parameterName: dataType) { statements }。
默认参数值
函数参数可以定义默认值,但必须在函数参数列表的最后。调用时,如果不指定参数的值,则使用默认值。
定义了默认值的函数参数会自动提供外部参数名,和局部参数名一样,也可以自己提供,如果不使用默认值,则必须在调用时使用外部参数名。
第3个参数joiner和第四个参数flag都是提供了默认参数值,自动提供了外部参数名joiner和flag,与局部参数名一致。joiner提供了值,则必须使用参数名joiner: "-"。flag使用默认值,则不需要在调用时出现。
可变参数
可变参数(variadic parameter)表示不确定数量的输入参数,在参数后加...表示。一个函数最多只能有一个可变参数, 且必须是参数列表的最后一个参数。
变量参数
Swift的函数参数采用值拷贝传递,传递进去的参数是不能进行修改的,如果我们需要,可以定义变量参数。在参数前加var定义变量参数。
string在函数内被修改了,但是作为局部变量,只能在函数内部使用。
输入输出参数
Swift的函数参数不能被修改,使用变量参数修改后也不能传递到外部,采用输入输出参数可以解决这个问题。
在参数前加inout定义输入输出参数。
- 函数调用时,输入输出参数只能传入变量
- 输入输出参数不能有默认参数值。
- 输入输出参数不能是可变参数。123456func appendCharacter(inout string: String, flag: Character) {string.append(flag)}var originalString = "hello"appendCharacter(&originalString, "!")// originalString is equal to "hello!"
appendCharacter函数传入参数时,在输入输出参数前必须加&前缀。
函数类型
函数类型和其他类型一样,可以定义并赋值,如:
同样函数类型可以作为函数的参数类型和返回类型,形式如func printMathResult(mathFunction: (Int, Int) -> Int, a: Int, b: Int)和func chooseStepFunction(backwards: Bool) -> (Int) -> Int。前者的一个参数为mathFunction: (Int, Int) -> Int,后者的返回(Int) -> Int,都没有func关键字。
函数也支持嵌套函数,在函数A内部定义的函数B只能在函数A内调用。
闭包
闭包表达式
闭包指自包含的函数代码块,可以在代码中被传递和使用。
函数就是特殊的闭包。
闭包的一般形式:{ (parameters) -> returnType in statements }
和函数不同的是,用in`替代了原本函数的大括号,并在最外层加上大括号。
sorted函数需要两个参数,第一个参数是需要排序的数组,第二个参数是确定排序顺序的闭包函数,传入与数组类型相同的两个值,并返回Bool值。如果第二个参数返回true则两个数组元素顺序不变;如果第二个参数返回false则两个数组元素顺序相反。
所以闭包函数中定义return s1 > s2,如果s1大于s2顺序不变,如果s1不大于s2则交换s1和s2的顺序,使值大的元素排在数组的前列,也就是逆序排列。
就上面的代码改为闭包表达式的形式为:
用闭包表达式代替了闭包函数,in替换函数的大括号,并在外层添加大括号。
闭包表达式的参数类型由第一个参数数组元素的类型决定,返回类型确定为Bool型,创建闭包时可以省略已知的信息:
闭包表达式中,如果只有单行表达式,比如return s1 > s2一行,可以省略return关键字:
闭包表达式的参数名称可以缩写成$0,$1,$2等,来顺序调用闭包参数:
另外,还可以用运算符函数(operator function)使闭包表达式更简短。因为>的定义就是接收两个参数,并返回Bool类型值,所以可以写:
尾随闭包(trailing closure):如果闭包表达是是函数的最后一个参数,可以把闭包放到函数的小括号后面,增强可读性:
如果闭包很长,尾随闭包就会非常有用。
如果函数中只有闭包一个参数,则可以省略小括号,写成reversed = sorted { $0 < $1 }的形式。
嵌套函数
嵌套函数是最简单的闭包形式。嵌套函数可以捕获外部函数的参数和定义的常量变量。
incrementor函数调用的amount是外部函数的参数,捕获并存储了副本;runningTotal会被修改,所以不可以是副本,而是捕获了一个引用,就算外部函数结束都不会消失。Swift会自动决定捕获引用还是副本。
incrementByTen创建时,runningTotal也创建了,每调用一次函数其值就会增加10。incremetnBySeven创建时,一个新的runningTotal也创建了,每调用一次函数其值就会增加7。这个变量和incrementByTen中的变量没有任何关系,互不干扰。
注意:无论是函数还是闭包,在赋值给常量或变量时都是引用拷贝,指向的是同一个函数/闭包对象。
转载请注明原作者和出处。
如果觉得这篇文章对您有帮助或启发,请随意打赏~
![]()
![]()
