值,那么这将确保形参对应的实参有着明确的目的。
?
为了使这个过程更容易,当你自己没有提供外部名称时,Swift将为你定义的任何默认形参提供一个自动外部名。这个自动外部名和本地名一样,就像你已经在本地名前添加了hash符号(#)一样。
?
这里有一个早期join函数版本,没有为任何外部形参提供外部名,但仍然提供了joiner形参的默认值:
- func join(s1: String, s2: String, joiner: String = ) -> String {
- return s1 + joiner + s2
- }
?
在这种情况下,Swift为带默认值的形参提供了外部形参名,当调用该函数的时候,外部形参名必须让形参的目的明确无歧义:
- join(hello, world, joiner: -)
- // returns hello-world
| 注意:在定义形参时,你可以通过使用下划线(_)来代替显示外部名称。不过在适当的情况下,带有默认值形参的外部名通常是优先推荐的。 |
可变形参
一个可变形参可接受零个或多个指定类型的值。当函数被调用时,你可以使用可变形参来指定--形参可以用来传递任意数量的输入值。可通过在形参的类型名后边插入三个点符号(...)来编写可变形参。
?
传递至可变形参的值在函数主体内是以适当类型的数组存在的。例如,一个可变参数的名称为numbers和类型为Double...在函数体内就作为名为numbers类型为Double[]的常量数组。
?
下边示例为任何长度的数字列表计算算术平均值:
- func arithmeticMean(numbers: Double...) -> Double {
- var total: Double = 0
- for number in numbers {
- total += number
- }
- return total / Double(numbers.count)
- }
- arithmeticMean(1, 2, 3, 4, 5)
- // returns 3.0, which is the arithmetic mean of these five numbers
- arithmeticMean(3, 8, 19)
- // returns 10.0, which is the arithmetic mean of these three numbers
| 注意:函数最多可以有一个可变形参,而且它必须出现在参数列表的最后,以避免使用多个形参调用函数引发歧义。如果你的函数有一个或多个带有默认值的形参,并且还有可变形参,请将可变形参放在所有默认形参之后,也就是的列表的最末尾。 |
?
常量形参和变量形参
函数的形参默认是常量。试图在函数体内改变函数形参的值会引发一个编译时错误。这意味着你不能错误地改变形参的值。
?
但是有时候,函数有一个形参值的变量副本是非常有用的。您可以指定一个或多个形参作为变量形参,从而避免在函数内部为自己定义一个新的变量。变量参数是变量而非常量,并给函数一个可修改的形参值副本。
?
在参数名称前用关键字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 is equal to -----hello
- // originalString is still equal to hello
这个例子定义了一个新函数叫做alignRight,用于将一个输入字符串和更长的输出字符串右边缘对齐。所有左侧的空白使用指定的占位符来填充。在这个例子中,字符串hello被转化为字符串-----hello。
?
alignRight函数把输入的形参字符串定义成一个变量形参。这意味着字符串现在可以作为一个本地变量,用传入的字符串值初始化,并且可以在函数体中进行相应操作。
?
函数首先要找出有多少字符需要被添加到字符串的左侧,从而在整个字符串中靠右对齐。这个值存储在本地常量amountToPad中。该函数然后将填充字符的amountToPad个字符拷贝到现有的字符串的左边,并返回结果。
| 注意:你对变量形参所做的改变不会比调用函数更持久,并且在函数体外是不可见的。变量形参仅存在于函数调用的声明周期中。 |
In-Out 形参
如上描述,变量形参只能在函数本身内改变。如果你想让函数改变形参值,并想要在函数调用结束后保持形参值的改变,那你可以把形参定义为in-out形参。
?
通过在形参定义的开始添加inout关键字来编写in-out形参。In-Out形参有一个传递至函数的值,由函数修改,并从函数返回来替换原来的值。
?
你只能传递一个变量作为in-out形参对应的实参。你不能传递一个常量或者字面量作为实参,因为常量和字面量不能被修改。当你把变量作为实参传递给in out形参时,需要在直接在变量前添加 & 符号,以表明它可以被函数修改。
| 提示:in-out参数不能有默认值,可变参数的参数也不能被标记为inout。如果您标记参数为inout,它不能同时被标记为var或let。 |
这里的一个叫做swapTwoInts函数,它有两个称为a和b的in-out整型形参:
- func swapTwoInts(inout a: Int, inout b: Int) {
- let temporaryA = a
- a = b
- b = temporaryA
- }
swapTwoInts函数只是简单地交换a、b的值。该函数通过存储一个名为temporaryA临时常量的值,指定b的值到a,然后分配temporaryA到b执行该交换。
?
你可以通过两个Int类型的变量调用swapTwoInts函数,从而交换它们的值。需要注意的是当它们被传递给swapTwoInts函数时,someInt和anotherInt名称前要加上前缀符号&:
- var someInt = 3
- var anotherInt = 107
- swapTwoInts(&someInt, &anotherInt)
- println(someInt is now (someInt), and anotherInt is now (anotherInt))
- // prints someInt is now 107, and anotherInt is now 3
上面的例子表明,someInt和anotherInt的原始值由swapTwoInts函数进行了修改,即使它们定义在函数外部。
| 注意:In-out形参不同于从函数返回一个值。上边swapTwoInts例子没有定义返回类型或者返回值,但它仍然会修改someInt和anotherInt的值。对函数来说,In-out形参是一个影响函数主体范围外的可选方式。 |
?
函数类型
每一个函数都有特定的函数类型,由函数的形参类型和返回类型组成。例如:
- func addTwoInts(