SwiftNote-5
2016年05月01日 Swift

函数

函数做为抽象的最基本构成元素,几乎是编程语言里绝不可缺少的。Swift的函数足够灵活,可以有各种使用方式。

函数定义和调用

  • 函数定义

    函数定义使用func关键字,后跟函数名,其后是参数小括号,内部是参数列表,如果有返回值,后接一个->(一个中划线后一个右尖括号),其后接返回值类型,下面加上大括号内部加上实现,就是一个完整的函数体。

    1
    2
    3
    4
    func 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
    12
    func 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
    18
    func 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
    10
    func 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
    34
    func 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
    26
    func 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
    9
    var 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
    24
    func 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
    12
    func makePowerOf2() -> (Int)->Int
    {
    // 生成一个计算二次方结果的函数
    func power2(num:Int)->Int
    {
    return num * num
    }
    return power2
    }

    let power2 = makePowerOf2()
    print( (power2(12))) // 144