Swift3.0学习笔记-Functions

         Swift的函数跟其它语言如C/Java是一样的, 都是由返回值、函数名称、函数参数等3要素组成。  区别是Swift使用关键字func来定义函数, func关键字类似于Python语言的def或者JavaScript的function。

       在主流编程语言Java/C++/Object-C中定义函数, 是这个样子的:

       返回值     函数名称(类型 参数1,  类型  参数2...)  {

               代码

       }

       //例如用Java写一个最简单的字符串判空函数

       boolean  hasStr(String value) {

              if (value == null) {

                   return false;

              }

              if (value.length() == 0) {

                    return false;

              } else {

                    return true;

              }

       }

       //Swift是长这样的

       func hasStr(value: String) -> Bool {

             guard let tmp = value else {

                   return false     

             }

             if value.isEmpty {

                  return true

              } else {

                  return false

             }

       }


        但在Swift里怎样做呢? 我觉得苹果肯定是脑洞大开了, 修改了定义函数的语法, 目前没搞明白苹果为什么这样做。Swift声明函数的语法长这样:

       func   函数名称(参数1: 类型,  参数2:  类型 ...)   -> 返回值类型  {

       }

      func关键字放在最前面,  返回值类型放在最后面,   使用->分隔参数和返回值类型。 看着有点别扭有没有? 下面看一下Swift和Java函数声明的区别:

    func greet(person: String) -> String { //Swift写法
        let greeting = "Hello, " + person + "!"
        return greeting
    }
   public String greet(String person) {      //Java写法
       String tmp = "Hello" + person + "!";
       return tmp;
   }

 在Java/C/Object-C语言里当函数无返回值时, 使用void作为返回值类型, 例如: public void greet(String person)。

在Swift语言中如果函数无返回值, 就不用写->和返回值类型了。例如:

func greet(person: String) {     //省略->和返回值类型
    print("Hello, \(person)!")
}
greet(person: "Dave")     //注意函数调用时的参数赋值, 这个跟Object-C语法是一样的。
输出 Hello, Dave"

  备注: 在Swift声明函数时func关键字、函数名称是必须有的, 函数参数、->和返回值类型是可选的!


   前一篇Control Flow将到switch-case可以使用键值对(x, y)作为参数, Swift的函数返回值也可以,支持多个返回值(但Java/C/OC只能是一个变量或对象), 这些返回值参数可以在函数体内读写。  例如下面函数是得到一个数组中的最大数和最小数。说明:   下面函数是以2个参数为例, 还可以是3个、4个或者更多参数。

    func minMax(array: [Int]) -> (min: Int, max: Int) {
        var currentMin = array[0]
        var currentMax = array[0]
        for value in array[1..<array.count] {
            if value < currentMin {
                currentMin = value
            } else if value > currentMax {
                currentMax = value
            }
        }
        return (currentMin, currentMax)
    }

    let bounds = minMax(array: [8, -6, 2, 109, 3, 71])   //<strong><span style="color:#FF0000;">注意:Swift数组用[], Java/C/OC数组用{}</span></strong>
    print("min is \(bounds.min) and max is \(bounds.max)")
    // 输出 "min is -6 and max is 109"


       还记得Swift的Optional类型吧, 就是像String? 、Int?这样在数据类型后面跟个问号, 表示它可能是nil。 当函数返回值可能有值或无值时,  就需要用Optional类型。 从而当函数体代码逻辑不满足时, 函数返回值是nil, 相当于Java的返回null。

    func minMax(array: [Int]) -> (min: Int, max: Int)? {
        if array.isEmpty { return nil }
        var currentMin = array[0]
        var currentMax = array[0]
        for value in array[1..<array.count] {
            if value < currentMin {
                currentMin = value
            } else if value > currentMax {
                currentMax = value
            }
        }
        return (currentMin, currentMax)
    }

      因为函数minMax可能返回nil或者键值对(x, y), 所以要判断是否nil再引用。

    if let bounds = minMax(array: [8, -6, 2, 109, 3, 71]) {   //bounds不等于nil时执行函数体,即先判空再使用
        print("min is \(bounds.min) and max is \(bounds.max)")  //注意调用方法, .min和.max
    }
    // 输出"min is -6 and max is 109"

      还记得switch-case里的下划线吗?  如果你不想每次调用函数时都写参数名称, 那么在声明函数时带上下划线。 语法如下:

    func someFunction(_ firstParameterName: Int, secondParameterName: Int) {
        // In the function body, firstParameterName and secondParameterName
        // refer to the argument values for the first and second parameters.
    }
    someFunction(1, secondParameterName: 2)  //调用函数时省去了firstParameterName
    说明:     像firstParameterName那样所有函数参数都加下划线, 就跟Java/C调用函数一样了,  不用写烦人的参数名称了(跟Object-C语法类似)。

        Swift跟Java/C语言语法一样,  定义函数时可以给参数一个默认值,  当它是最后一个参数时, 在调用该函数时可以不写最后一个参数。 格式如下:

        func  函数名称(类型: 参数1,  类型: 参数2 =   某个值, ...)  -> 返回值 {

        }

func someFunction(parameterWithoutDefault: Int, parameterWithDefault: Int = 12) {
    // 可以省略最后一个参数parameterWithDefault, 但在函数体内它的值是12
}
someFunction(parameterWithoutDefault: 3, parameterWithDefault: 6) // parameterWithDefault是 6
someFunction(parameterWithoutDefault: 4) //<strong><span style="color:#FF0000;">只写1个参数,但第2个参数parameterWithDefault初值是12</span></strong>

当不确定函数参数有多少个时, 该怎么办?  Java语法是这样写的

    public void arithmeticMean(double ... values) {
        for (double value:values) {
            System.out.println(value);
        }
    }
    arithmeticMean(0.0, 0.1, 0.2);
    double[] group = {0.0, 0.1, 0.2};
    arithmeticMean(group);   //和arithmeticMean(0.0, 0.1, 0.2)执行结果一致!!!
备注: Java使用...表示若干个参数, 其实就是个数组!


Swift语言同样使用...表示若干个参数(注意:这些参数必须是同一个数据类型!),  区别是Java使用冒号, Swift使用in遍历数组。

func arithmeticMean(_ numbers: Double...) -> Double {   //numbers意义类似于Double型数组
    var total: Double = 0
    for number in numbers {      //注意区别:Swift遍历用关键字in, Java是:
        total += number
    }
    return total / Double(numbers.count)
}
arithmeticMean(1, 2, 3, 4, 5)       //函数调用方式同Java/C, 因为声明函数时使用了下划线!
// 返回值3.0
arithmeticMean(3, 8.25, 18.75)
// 返回10.0


       在Java语法里一般会要求将参数声明为常量final, 在函数体内不允许修改参数值; 但如果你非要修改的话, Java编译器也不会报错, 但是Java编码规范里要求不要改参数值!!!    Java老司机是不会在函数体内修改参数值的。

      如果你懂得C语言,  应该知道值引用的概念, 最典型的demo函数是交换2个int值, 即

void swap(int &a, int &b) {

     int tmp = a;

     a = b;

     b = tmp;

}

      在Swift语法里默认是不允许修改函数参数的,  但为了支持修改参数值, Swift提供了关键字inout, 作用跟C语言的引用&完全一样, 大概就是学的C语言吧。语法如下:

    func swapTwoInts(_ a: inout Int, _ b: inout Int) {  //参数类型前添加inout关键字,表示参数可修改!
        let temporaryA = a
        a = b
        b = temporaryA
    }
    var someInt = 3
    var anotherInt = 107
    swapTwoInts(&someInt, &anotherInt)  //注意参数前面有个&, 可以理解为引用;如果不加&是不会改变的!
    print("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
    // 输出"someInt is now 107, and anotherInt is now 3"

     上面是Swift交换2个Int值的写法, 跟C语言的swap函数作用完全一样, 都要用&操作符,可以理解为值引用。


Function Types: Swift函数类型(类似于C语言的函数指针),  参数个数、类型完全一样而且返回值类型相同, 则函数名称可作为值赋给函数类型变量。

   func addTwoInts(_ a: Int, _ b: Int) -> Int {
        return a + b
    }
    func multiplyTwoInts(_ a: Int, _ b: Int) -> Int {
        return a * b
    }


    var mathFunction: (Int, Int) -> Int = addTwoInts      //mathFunction是函数类型
    等价于
    var mathFunction: (Int, Int) -> Int
    mathFunction = addTwoInts

    print("Result: \(mathFunction(2, 3))")
    // 打印"Result: 5"

    mathFunction = multiplyTwoInts   
    print("Result: \(mathFunction(2, 3))")
    //  打印 "Result: 6"
说明:  mathFuntion是个变量, 类型是函数。 mathFunction/addTwoInts/multiplyTwoInts的参数、返回值类型都一样, 所以可以将multipleTwoInts或者addTwoInts赋值给mathFunction。 用法跟C语言函数指针完全相同, 但我觉得实际编码中用处不大, 直接调用函数就好了, 为什么要用函数指针呢?  所以不建议使用该特性,  我写C/C++代码时就从没用过函数指针!


函数类型还可以用作函数参数类型, 即将函数指针传入函数体, 然并卵??? Swift开发这个特性干什么用? 在函数体内直接调用函数好不好, 脑洞大开也没想明白这个语法的好处!

    func printMathResult(_ mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) {
        print("Result: \(mathFunction(a, b))")
    }
    printMathResult(addTwoInts, 3, 5)
    // 输出"Result: 8"
备注: 我觉得知道Swift有这个语法就可以了, 在实际编码中不建议使用这个用法!


Swift既然能让函数类型当做参数, 那么当然也可以是返回值了。

   func stepForward(_ input: Int) -> Int {
        return input + 1
    }
    func stepBackward(_ input: Int) -> Int {
        return input - 1
    }

    func chooseStepFunction(backward: Bool) -> (Int) -> Int {   //标红部分表示是函数类型,  只有1个整型参数,返回值是整型。
        return backward ? stepBackward : stepForward
    }

    var currentValue = 3
    let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
    // moveNearerToZero指向stepBackward() 函数


内部函数, 顾名思义在函数体内再定义函数, 语法和用法同全局函数, 在函数体外无法访问!

func chooseStepFunction(backward: Bool) -> (Int) -> Int {  //chooseStepFunction是全局函数
    func stepForward(input: Int) -> Int { return input + 1 }    //stepForward是内部函数
    func stepBackward(input: Int) -> Int { return input - 1 }
    return backward ? stepBackward : stepForward
}

         总结:  Swift的函数跟其它语言的函数一样,都是为了执行一段代码和输出执行结果, 它参考了C语言的很多语法,区别是Swift定义函数的语法稍微有些差别,  新定义了关键字func; 在函数指针功能上, 更是跟C语言如初一辙。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值