在Swift中对于函数的定义 / 使用中一些不同于C的特点和一些应该注意的细节:
- Swift中函数的定义
使用 func 函数名(参数列表) ->返回值类型{函数体} - 函数的形参和返回值
不同于C中的函数,在swift中函数可以有多个返回值, 这可以由元组来实现,. 外部参数名:
如果希望使用该函数的人在调用函数时提供形参名称,那就需要用到一个外部形参。只需要写一个外部形参名称在它所支持的本地形参名称之前, 之间只需要用一个空格来分隔://string 是 s1的外部参数名, s1是内部参数名作用域在函数内部,所以只能在函数内部使用, func join(string s1: String, toString s2: String, withJoiner joiner: String) -> String { return s1 + joiner + s2 }
外部形参名必须在调用时使用, 使用外部形参名可以更清楚调用函数:
join(string: "hello", toString: "world", withJoiner: ", ")
如果想让外部参数名和内部参数名相同, 可以只写一个参数名字在这个参数名之前加上一个 # 作为前缀, 这就告诉Swift使用名称相同的本地形参名称和外部形参名称。
//如上例中的join函数可以写为: func join( #string: String, #toString: String, #withJoiner: String) -> String { return s1 + joiner + s2 }
默认形参值
默认形参值的设置可以说是函数定义中的一部分, 如果定义了默认值, 那么调用函数时就可以省略该形参.
注意:应该在函数形参列表的末尾放置带默认值的形参。这将确保所有函数调用都使用顺序相同的无默认值实参,并让在每种情况下清晰地调用相同的函数。func join(string s1: String, toString s2: String, withJoiner joiner: String = " ") -> String { return s1 + joiner + s2 }
如果在join函数调用时为joiner提供了字符串值,那么该字符串值可以用来连接两个字符串,就跟以前一样:
println(join(string: "hello", toString: "world", withJoiner: "-")) //输出为 hello-world
但是,如果函数调用时没有为joiner提供值,就会使用单个空格(” “)的默认值:
println(join(string: "hello", toString: "world")) //输出为 hello world
可变形参
可变形参可以接受一个或多个指定类型的值, 使形参可以传递任意数量的输入值,
可变形参的写法, 可以在形参的类型后面插入(…)来编写可变形参func arithmeticMean(numbers: Double...) -> Double { var total: Double = 0 for number in numbers { total += number } return total / Double(numbers.count) } //可以输入Double类型的任意数量的形参 arithmeticMean(1, 2, 3, 4, 5) // returns 3.0 arithmeticMean(3, 8, 19) // returns 10.0
注意: 函数最多可以有一个可变形参,而且它必须出现在参数列表的最后,以避免使用多个形参调用函数引发歧义。如果函数有一个或多个带有默认值的形参,并且还有可变形参,应该将可变形参放在所有默认形参之后,也就是的列表的最末尾。
常量形参和变量形参
在函数中的形参默认为是常量, 如果要定义变量形参可以在参数名称前用关键字var定义变量参数, 这样在函数内形参的值就可以改变了func alignRight(var string: String, count: Int, pad: Character) -> String { let amountToPad = count - countElements(string) for _ in 1...amountToPad { string = pad + string //改变了形参的值 } return string } let originalString = "hello" let paddedString = alignRight(originalString, 10, "-") // paddedString的值变为 "-----hello"
值得注意的是:对变量形参的作用域也只是在函数内部,所以在函数体外是不可见的。变量形参仅存在于函数调用的声明周期中。
In-Out形参
如上面的变量形参只是在函数的内部改变, 如果要让函数改变形参的值, 并想要在函数调用结束后保持形参值的改变, 则可以把形参定义为in-out形参 .
可以在形参定义的前面添加inout关键字来定义in-out形参。In-Out形参有一个值传递至函数,由函数修改后,从函数返回来替换原来的值。
应该注意只能传递一个变量作为in-out形参对应的实参。你不能传递一个常量或者字面量作为实参,因为常量和字面量不能被修改。当你把变量作为实参传递给in out形参时,需要在变量前添加 & 符号,以表明它可以被函数修改。in-out参数不能有默认值,可变参数的参数也不能被标记为inout。如果标记参数为inut,它就不能同时被标记为var或let。
这里的一个叫做swapTwoInts函数,它有两个称为a和b的inout整型形参:func swapTwoInts(inout a: Int, inout b: Int) { let temporaryA = a a = b b = temporaryA } var someInt = 3 var anotherInt = 107
//需要注意的是当它们被传递给swapTwoInts函数时,someInt和anotherInt名称前要加上前缀符号&:
swapTwoInts(&someInt, &anotherInt) // 这时 someInt = 107 而 anotherInt = 3
值得注意的是:对函数来说,In-out形参是一个影响函数主体范围外的可选方式。
函数类型
函数的类型由函数的形参类型和返回值类型组成func addTwoInts (a : Int , b :Int) -> Int { return a + b } // 该函数的类型为(Int, Int) ->Int
在swift中课可以像使用其他类型一样使用函数类型 .可以定义一个常量或是变量为函数类型, 并为其指定一个对应的函数, 这时就可以使用math来调用指定的函数:
var math : (Int , Int) - > Int = addTwoInts println ("Result: \(math(2, 3))")
具有相同匹配类型的不同函数可以被赋给同一个变量,和非函数类型一样.
函数类型做形参
func printMath (math :(Int , Int) ->Int, a : Int , b: Int) { println("Result: \(mathFunction(a, b))") } printMath(addTwoInts, 7, 9)
函数做返回值
func stepForward(input: Int) -> Int { return input + 1 } func stepBackward(input: Int) -> Int { return input - 1 }
这里有一个chooseStepFunction函数,它的返回类型是”函数类型(Int) -> Int”。chooseStepFunction基于名为backwards的布尔形参返回stepBackward或stepForward函数:
func chooseStepFunction(backwards: Bool) -> (Int) -> Int { return backwards ? stepBackward : stepForward }
可以使用chooseStepFunction获取一个函数,可能是递增函数或递减函数:
var currentValue = 3 let moveNearerToZero = chooseStepFunction(currentValue > 0)
由于布尔值为真,则返回stepBackward函数存储moveNearerToZero里。
嵌套函数
嵌套函数默认对外界是隐藏的,但仍然可以通过它们包裹的函数调用和使用它。enclosing function也可以返回一个嵌套函数,以便在其他作用域中使用嵌套函数。
重写上面的chooseStepFunction函数使用并返回嵌套函数:
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(currentValue > 0)