1.函数的定义
// 无返回值的情况
func sayHello() {
print("Hello")
}
func sayHello1()->(){
print("Hello2")
}
func sayHello3()-> Void{
print("Hello3")
}
形参是let,也只能是let
2.隐式返回
如果整个函数就一个单一表达式,那么函数会隐式返回这个表达式.和js中的箭头函数是一样的
func sum1(v1:Int, v2:Int) -> Int {
v1 + v2
}
sum1(v1: 20, v2: 30)
3.返回元祖:实现多返回值
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)
print("sum",result.sum)
4.函数的文档注释
/// 求和【概述】
///
/// 将2个整数相加【更详细的描述】
///
/// - Parameter v1: 第一个整数
/// - Parameter v2: 第二个整数
/// - Returns: 2个整数的和
///
/// - Note:传入2个整数即可【批注】
func sum(v1:Int,v2:Int) ->Int {
return v1 + v2
}
sum(v1: 10, v2: 20)
5.参数标签 (Argument Label)
可修改参数标签
func gotoWork(at time: String){
print("this time is \(time)")
}
gotoWork(at: "08:00")
//可以使用下划线 _ 省略参数标签
func sum3(_ v1: Int, _ v2: Int) -> Int {
v1 + v2
}
sum3(30, 30)
6.默认参数值(Default Parameter Value)
// 参数可以有默认值
func check(name: String = "nobody", age:Int, job:String = "none"){
print("name=\(name),age=\(age),job=\(job)")
}
check(name: "Jack", age: 20, job: "Doctor")
check(age:19, job: "cook")
check(age: 10)
//C++ 的默认参数值有个限制:必须从右边往左设置。由于Swift拥有参数标签,因此并没有此类限制,但是在省略参数标签时,需要特别注意,避免出错
func test(_ first:Int = 10, middle:Int,_last:Int = 30){
}
test(middle:20)
7.可变参数(variadic parameter)
func sum(_ numbers:Int...) -> Int {
var total = 0
for num in numbers {
total += num
}
return total
}
sum(10,20,30,40,50)
- 一个函数最多只能有一个可变参数
- 紧跟在可变参数后面的参数不能省略参数标签
swift 自带的print函数使用
func test(_ numbers: Int..., string: String, _ other:String){
}
test(10,20,30,string:"Jack","Rose")
8.输入输出参数(In-Out Parameter)
- 可以使用inout 定义一个输入输出参数:可以在函数内部修改外部实参的值 注意点主要有以下几点:
- 可变参数不能标为inout
- inout参数不能有默认值
- inout 参数只能传入可以被多次赋值的
- inout 参数的本质是地址传递(引用传递)
func swapValues(_ v1:inout Int, _ v2:inout Int){
let tmp = v1
v1 = v2
v2 = tmp
}
var num1 = 10
var num2 = 20
swapValues(&num1, &num2)
print(num1,num2)
9.函数重载(Function overload)
什么叫函数重载,函数名相同,当参数个数,或者参数类型不同,或者参数标签不同的叫函数重载.这里需要注意的是返回值类型与函数重载无关
- 参数个数不同
func sum(v1:Int, v2:Int) -> Int {
v1 + v2
}
func sum (v1:Int, v2:Int, v3:Int) -> Int {
v1 + v2 + v3
}
2.参数类型不同
func sum(v1:Int, v2:Double)->Double {
Double(v1) +v2
}
func sum(v1:Double, v2:Int)->Double {
v1 +Double(v2)
}
3.参数标签不同
func sum(_ v1:Int, _ v2:Int) ->Int {
v1 + v2
}
func sum(a: Int,b: Int) ->Int {
a + b
}
其他细节
- 返回值类型与函数重载无关
func sum(v1: Int, v2:Int)->Int {v1 + v2}
//func sum(v1: Int, v2:Int) {}
//sum(v1:10, v2:20)
2.默认参数值和函数重载产生一起使用产生二义性,编译器并不会报错(在c++中会报错)
func sum(v1: Int, v2:Int)->Int {
v1 + v2
}
func sum(v1:Int, v2:Int, v3:Int = 10) ->Int {
v1 + v2 + v3
}
sum(v1:10,v2:20)
3.可变参数,省略参数标签,函数重载一起使用产生二义性时,编译器有可能会报错
func sum(v1:Int, v2:Int) -> Int {
v1 + v2
}
func sum (_ v1:Int, _ v2:Int) -> Int {
v1 + v2
}
func sum(_ numbers: Int ...)->Int {
var total = 0
for number in numbers {
total += number
}
return total
}
sum(10,20)
10.内联函数
如果开启了编译器优化(Release模式默认会开启优化),编译器会自动将某些函数变成内联函数
func testPrint() {
print("testPrint")
}
testPrint()
大白话解释下什么是内联函数?对于下面的函数来说,其实就是编译器直接会将testPrint()替换成print("testPrint"),前面的func testPrint() 直接没有了
特殊情况
哪些函数不会被自动内联?
- 函数体比较长
- 包含递归调用
- 包含动态派发
永远不会被内联的情况
@inline(never) func test1(){
print("test")
}
开启编译器优化后,即使代码很长,也会被内联(递归调用函数,动态派发的函数除外)
@inline(__always) func test(){
print("test")
}
在Release模式下,编译器已经开启优化,会自动决定哪些函数需要内联,因此没有必要使用 @inline
11.函数类型(Function Type)
每一个函数都是有类型的,函数类型由形式参数类型,返回值类型组成
func test(){}
上面函数的类型是 // ()->void 或者 ()->()
func sum(a:Int,b:Int)->Int {
a + b
}
上面函数的类型是 (Int, Int) -> Int
函数类型作为函数参数
func sum(v1: Int, v2:Int) -> Int {
v1 + v2
}
func difference(v1: Int, v2:Int) -> Int {
v1 - v2
}
func printResult(_ mathFn:(Int,Int)-> Int, _ a: Int, _ b:Int){
print("Result:\(mathFn(a,b))")
}
printResult(sum, 5, 2)
printResult(difference, 5, 2)
函数类型作为函数的返回值
func next(_ input: Int)->Int {
input + 1
}
func previous(_ input:Int)->Int {
input - 1
}
func forward(_ forward:Bool)-> (Int)->(Int) {
forward ? next : previous
}
forward(true)(3)
forward(false)(3)
返回值是函数类型的函数,叫做高阶函数
12.typealias 用来给类型起别名
typealias Byte = Int8
typealias Short = Int16
typealias Long = Int64
typealias Date = (year: Int, month:Int, day:Int)
func test(_ date:Date){
print(date.0)
print(date.year)
}
test((2021,9,10))
按照swift 标准库的定义,Void 就是空元祖()
Public typealias Void = ()
13.嵌套函数(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)
forward(false)(3)