函数
函数做为抽象的最基本构成元素,几乎是编程语言里绝不可缺少的。Swift的函数足够灵活,可以有各种使用方式。
函数定义和调用
函数定义
函数定义使用func关键字,后跟函数名,其后是参数小括号,内部是参数列表,如果有返回值,后接一个->(一个中划线后一个右尖括号),其后接返回值类型,下面加上大括号内部加上实现,就是一个完整的函数体。
1
2
3
4func hasRetVal(name:String) -> String
{
return name + "! Welcom to Earth!"
}函数调用
调用方式同其他语言类型,直接使用函数名小括号里加参数列表的形式调用
1
2
3// 二个函数调用都输出对应的欢迎语
noneRetVal("John")
print(hasRetVal("Nick"))
参数与返回值
参数
无参数,一个参数,多个参数三种,无参数的情况直接小括号留空即可,一个参数的直接在小括号内写明参数名与类型即可,多参数的用逗号分隔
1
2
3
4
5
6
7
8
9
10
11
12func noneParam()
{
print("None parameter function")
}
func oneParam(param:String)
{
print("Have 1 parameter")
}
func mulParam(para1:Int, para2:String, para3:Bool)
{
print("multiple parameters function")
}参数名称,(外部参数名与局部参数名)
函数都有一个外部参数名,意为由外部调用函数时候传参指定的参数名,局部参数名就是在函数体内部使用的参数名。局部参数必须不同,外部参数名可以相同,但是为了区分尽量外总参数也不同,通常的情况,不指定外部参数名的情况下,第一个参数省略参数名,后面的由局部参数名来当外部参数名,函数体显式指定外部参数名的时候,调用的时候必须指定外部参数名, 如果想忽略掉后面的外部参数名,在定义函数的时候,使用_(下划线)显式指定此参数需要指定外部参数名。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15// 指定外部参数的情况下,调用必须使用外部参数名
func externalFuncName(externalName localName :String, externalFlagName flagName:String)
{
print("localName = \(localName) flagName = \(flagName)")
}
// 调用的时候必须指明外部参数名
externalFuncName(externalName: "Name", externalFlagName: "1")
// 上面的例子中多参数函数,如下调用方式
mulParam(1, para2: "Swift", para3: false)
// 此处第二个参数忽略掉外部参数名,直接使用ignoreExternalParamName("str", 1)调用
func ignoreExternalParamName(first:String, _, second:Int)
{
}默认参数
像C++一样,Swift也提供了默认参数,即函数在调用的时候如果不传实参,函数体会使用默认参数的值,虽然Swift不像C++那样默认参数必须在最后,写的时候也最好将默认参数放在最后,这样不会导致非默认参数的传参顺序不会错乱。
1
2
3
4
5
6
7
8
9
10
11
12// 可以使用这种定义方式,但是不建议
func defaultValFunc(first:String, second:Bool = false, third:Int)
{
}
func gotoSomeWhere(location:String, date:String, isDrive:Bool = false)
{
print("我想在\(date)\(isDrive ? "开车" : "坐地铁") 去\(location)")
}
gotoSomeWhere("三亚", date: "2016年5月1日")
gotoSomeWhere("长城", date: "2016年6月1日", isDrive: true)变长参数
Swift定义长度不定的参数,使用…,0个或者多个参数值,前提是相同类型的参数,函数体内部可以像通过访问同类型的数组一样访问变长参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18func getAverage(varParamList:Int...) -> Float?
{
if varParamList.isEmpty
{
return nil
}
var sum:Int = 0
for num in varParamList
{
sum += num
}
return Float(sum) / Float(varParamList.count)
}
// 通过可选值绑定来获取平均值
if let avg = getAverage(1, 2, 4, 5, 6, 7)
{
print("average = \(avg)")
}输入输出参数,类似C++的引用,即在函数体内部需要修改实参的值,使用inout关键字修饰变量,并且在传实参的时在变量前使用&符号,实参类型只能是var声明的,也就是只能是变量,常量和字面量是不可以传参给inout修饰的参数值的,最常用的例子就是交换二个数
1
2
3
4
5
6
7
8
9
10func swap2Val(inout param1:Int, inout param2:Int)
{
let tmp = param1
param1 = param2
param2 = tmp
}
var p1 = 12
var p2 = 14
swap2Val(&p1, param2: &p2)返回值
无返回值,一个返回值,多个返回值三种情况,无返回值的情况不需要在函数定义用箭头标明返回值,一个返回值,直接由箭头处标明返回值类型,多个返回值使用元组,且内部标明类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34func getOneMax(array:[Int]) -> Int
{
var max:Int = 0
for num in array
{
if num > max
{
max = num
}
}
return max
}
func getMinAndMax(array:[Int]) -> (min:Int, max:Int)
{
var min, max:Int
min = Int.max
max = Int.min
for number in array
{
if number > max
{
max = number
}
if number < min
{
min = number
}
}
return (min, max) // 不需要再次在这里进行元组内部元素名称指定,在函数返回处已指定
}
getOneMax([1, 10, -1, 100])
let tpl = getMinAndMax([90, 100, 1000])
print("\(tpl.min)")可选元组的返回类型
实际编程中经常会遇到这种情况,就会返回多个的值元组可能为空的,这时候需要将元组指定为可选类型,这样在返回的时候使用可选绑定来确认是否返回值为空,上面的例子可以改为如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26func getMinAndMax(array:[Int]) -> (min:Int, max:Int)?
{
if array.isEmpty
{
return nil
}
var min, max:Int
min = Int.max
max = Int.min
for number in array
{
if number > max
{
max = number
}
if number < min
{
min = number
}
}
return (min, max)
}
if let tpl = getMinAndMax([90, 100, 1000])
{
print("\(tpl.min)")
}
函数类型
Swift中函数是first class, 可以做为变量传递,也可以做为函数参数和返回值,函数是有类型的,函数类型由参数列表和返回值来确定的,如(Int, Stirng)->Bool就代表参数是Int和String返回值是Bool的函数类型,这以使用这种类型创建一个变量,然后将某一个实现了的函数赋值给这个变量,然后就可以通过这个变量来调用那个函数
作为变量,函数类型的变量
1
2
3
4
5
6
7
8
9var add2Func:(Int, Int)->Int
func funcAdd2(fir:Int, _ sec:Int)->Int
{
return fir + sec
}
add2Func = funcAdd2
add2Func(1, 2) // 相当于调用funcAdd2作为函数参数
同变量差不多,只不过是写在另一个函数的参数列表里, 如同C语言的函数指针
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24func lessFunc(p1:Int, _ p2:Int)->Bool
{
return p1 <= p2
}
func sortIntArray(inout array:[Int], compare:(Int, Int)->Bool)
{
for i in 0 ..< array.count - 1
{
for j in 0 ..< array.count - 1 - i
{
if compare(array[j], array[j + 1])
{
let tmp = array[j]
array[j] = array[j + 1]
array[j + 1] = tmp
}
}
}
}
var intArray = [1, 3, 10, -1, 100, 99]
sortIntArray(&intArray, compare: lessFunc) // 函数作为比较的参数传入另一个函数中
print(intArray)作为另一个函数的返回值,同时包含了嵌套函数,可以在一个函数内定义另一个函数并将这个函数返回,如果变量赋值一样,返回后赋值给变量,可以直接用变量来调用这个函数内部定义的嵌套的函数
1
2
3
4
5
6
7
8
9
10
11
12func makePowerOf2() -> (Int)->Int
{
// 生成一个计算二次方结果的函数
func power2(num:Int)->Int
{
return num * num
}
return power2
}
let power2 = makePowerOf2()
print( (power2(12))) // 144