Swift从入门到精通第二篇 - 函数
函数
环境Xcode 11.0 beta4 swift 5.1
-
函数的定义
// func 函数名(参数列表) -> 返回值 { // 函数体 // } // 形参默认是`let`,也只能是`let` // 例如 func function(v1: Int, v2: Int) -> Int{ return v1 + v2 }
-
隐式返回(Implicit Return)
// 如果整个函数体是一个单一的表达式,那么函数会隐式返回这个表达式 func sum(v1: Int, v2: Int) -> Int { v1 + v2 } sum(v1: 10, v2: 20) // 30
-
返回元组:实现多返回值
func calculate(v1: Int, v2: Int) -> (sum: Int, difference: Int, average: Int){ let sum = v1 + v2 return (sum, v1 - v2, sum >> 1) } let result = calculate(v1: 20, v2: 10) result.sum // 30 or result.0 result.difference // 10 or result.1 result.average // 15 or result.2
-
函数文档注释
[Swift官方文档注释指导规范] -
参数标签
// at 参数标签 time 参数名称 func goToWork(at time: String){ print("this time is \(time)") } goToWork(at: "09:00") // 参数标签省略 func goToWork2(_ time: String){ print("this time is \(time)") } goToWork2("09:00") func goToWork3(time: String) { print("this time is \(time)") } goToWork3(time: "09:00")
-
默认参数值(Default Parameter Value)
- 参数可以有默认值,由于有参数标签可以不用像C++那样必须从右到左设置参数默认值
func check(name: String = "nobody", age: Int, job: String = "none"){ print("name = \(name), age = \(age), job = \(job)") } check(name: "Jack", age: 18, job: "Actor") check(name: "Rose", age: 18) check(age: 18)
- 注意:当有其它参数有默认参数时,没有设置默认参数的参数标签是不能省略的
-
可变参数(Variadic Parameter)
func sum(_ numbers: Int...) -> Int{ var total = 0 for number in numbers { total += number } return total } sum(1, 2, 3, 4) // 10
- 一个函数最多只能有一个可变参数
- 紧跟在可变参数后面的参数不能省略参数标签
// 参数string不能省略标签 func test(_ numbers: Int..., string: String, _ other: String){ }
-
输入输出参数(In-Out-Parameter)
- 可以用
inout
定义一个输入输出参数:可以在函数内部修改外部实参的值
func swapValues(_ v1: inout Int, _ v2: inout Int) { let tmp = v1 v1 = v2 v2 = tmp } func swapValues2(_ v1: inout Int, _ v2: inout Int) { (v1, v2) = (v2, v1) }
- 可变参数不能标记为
inout
inout
参数不能有默认值inout
参数只能传入可以被多次赋值的inout
参数的本质是地址传递(引用传递)
- 可以用
-
函数重载
- 规则
函数名相同
参数个数不同或参数类型不同或参数标签不同// 参数个数不同 func sum(v1: Int, v2: Int) -> Int { v1 + v2 } func sum(v1: Int, v2: Int, v3: Int) -> Int { v1 + v2 + v3 }
// 参数类型不同 func sum(v1: Int, v2: Double) -> Double { Double(v1) + v2 } func sum(v1: Double, v2: Int) -> Double { v1 + Double(v2) }
// 参数标签不同 func sum(_ v1: Int, _ v2: Int) -> Int { v1 + v2 } func sum(a: Int, b: Int) -> Int { a + b }
- 重载注意点
返回值类型与重载无关
默认参数和函数重载同时使用时在C++中会报错,但在Swift中有时不会,如下func sum(v1: Int, v2: Int) -> Int { v1 + v2 } func sum(v1: Int, v2: Int, v3: Int = 10) -> Int { v1 + v2 + v3 } sum(v1: 1, v2: 2) // 会调用sum(v1: Int, v2: Int)
可变参数、省略参数标签、函数重载三者同时使用产生二义性,如下
func sum(_ numbers: Int...) -> Int{ var total = 0 for number in numbers { total += number } return total } func sum(_ v1: Int, _ v2: Int) -> Int { v1 + v2 } func sum(v1: Int, v2: Int) -> Int { v1 - v2 }
- 上面任意两个同时使用在当前环境下并不会报错
-
嵌套函数(Nested Function)
将函数定义在函数内部
func forward(_ forward: Bool) -> (Int) -> Int { func next(_ input: Int) -> Int { input + 1 } func previous(_ input: Int) -> Int { input - 1 } return forward ? next : previous } // forward(true)(3) // 4 // forward(false)(3) // 2