美文网首页
04-Swift函数(Functions)

04-Swift函数(Functions)

作者: 王梓懿_1fbc | 来源:发表于2018-10-20 17:34 被阅读15次

    函数是用来完成特定任务的独立的代码块。可以给函数起一个名字,用于标识一个函数,当函数需要执行的时候,这个名字就会用于"调用"函数。
     在swift中,每个函数都有一种类型,包括函数的参数值类型和返回值类型。你可以把函数类型当做和其他普通变量类型一样处理,这就可以更简单的把函数当做其他的函数的参数,也可以从其他函数中返回函数。

    一、函数定义与调用

    • 函数的定义与调用。func是函数的关键字,参数是在函数名后的括号中,指定函数返回值类型时,用返回箭头->后面跟着返回类型的方法是来表示。
    /** 
    func前缀即表示为函数
    函数名: sayHello
    参数名: persionName,类型是String 
    返回值: 返回值是String类型的
    */
    func sayHello(personName:String) -> String {
        let getString = "hello," + personName;
        return getString;
    }
    // 函数的调用
    let str = sayHello("EndEvent");
    print(str);
    输出结果: hello,EndEvent
    

    二、函数参数与返回值

    • 无参函数,即函数可以是没有参数的:
    func speak() -> String{
        // 返回字符串
        return "hello Swift!";   
    }
    // 函数调用
    print(speak());
    输出结果: hello Swift!
    
    • 多参函数,多个参数以,逗号分隔:
    // 参数1: name;   参数2: age;
    func sayHi(name:String, age:Int) -> String {
        return "hi,我叫\(name),今年\(age)岁.";
    }
    print(sayHi("EndEvent", age: 20));
    输出结果: hi,我叫EndEvent,今年20岁.
    
    • 无返回值函数,即没有返回值:
    func sayBye(name:String) {
        print("Bye \(name)!");
    }
    sayBye("EndEvent");
    // 输出结果: Bye EndEvent!
    
    (备注: 虽然没有返回值定义,但实际`sayBye(_:)`函数依然是返回了值。这是一个特殊的返回值,叫`void`。其实返回是一个空的元组`tuple`,没有任何元素可以写成`()`)
    
    • 多重返回值函数,可以用元组(tuple)类型让多个值作为一个复合值返回:
    // 该函数中带3个参数,返回值是一个元组
    func getMaxAndMinValue(a:Int, b:Int, c:Int) -> (max:Int, min:Int){
        // 计算最大值的方法(系统自带)
        let maxValue = max(a, b, c);
        // 计算最小值的方法(系统自带)
        let minValue = min(a, b, c);
        
        return (maxValue,minValue);
    }
    let temp = getMaxAndMinValue(10, b: 3, c: 11);
    // 因为元组成员值已命名,即可用点语法
    print("maxValue:\(temp.max)");
    print("minValue:\(temp.min)");
    输出结果: 
    maxValue:11
    minValue:3
    
    • 可选元组返回类型。如果函数返回的元组类型,可能整个元组都是"空的",那么久可以使用* 可选的(Optional) *元组进行返回,这就表示整个元组是nil。例如(Int, Int)?、(String, String)?。
    func getMaxAndMinValue(array: [Int]) -> (max: Int, min: 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 (currentMax, currentMin)
    }
    // 函数调用,不为空才打印输出
    if let temp = getMaxAndMinValue([10,3,13,100,-50]) {
        print("maxValue:\(temp.max)");
        print("minValue:\(temp.min)");
    }
    输出结果:
    maxValue:100
    minValue:-50
    

    注意: 可选元组类型如(Int, Int)?和 元组中包含可选类型如(Int?, Int?)是不一样的。可选的元组类型,整个元组是可选的,而不是元组中的每个元组值。

    三、函数参数名称

    函数参数都有一个* 外部参数名 和 一个 局部参数名 *。外部参数名用于在函数调用时标注传递给函数的参数,内部参数名在函数的内部使用。
     一般情况下,第一个参数省略其外部参数名,第二个以及随后的参数使用其局部参数名作为外部参数名。所有局部参数名必须是独一无二的。尽管多个参数可以有相同的外部参数名,但不同的外部参数名可以提高代码的可读性。

    • 指定外部参数名
    // firstName: 第一个参数的外部参数名
    // name: 第一个参数的内部参数
    func sayHello (firstName name:String) {
        print("hello \(name)");
        // 错误的,因为外部参数只用于标注传递
        // print("hello \(firstName)"); 
    }
    // 有提供外部参数名,在调用时,必须使用外部参数名!!!
    sayHello(firstName: "EndEvent");
    输出结果: hello EndEvent
    
    // 外部参数名和内部参数名可以是一样的
    func sayHello (name name:String) {
        print("hello \(name)");
    }
    sayHello(name: "EndEvent");
    输出结果: hello EndEvent
    
    // 所有外部参数名都可以是一样的,即都为name
    // 内部参数名是要在函数内使用,所以必须是不同
    func sayHello (name name1:String, name name2:String) {
        print("hello \(name1)");
        print("hello \(name2)");
    }
    sayHello(name: "EndEvent", name: "Swift");
    输出结果:
    
    hello EndEvent
    hello Swift
    
    • 忽略外部参数,如果不想为第二个以及后续的参数设置外部参数名,可以用_来代替一个明确的参数名:
    // 第一个参数默认忽略其外部参数名称,显式写下划线是多余的
    func sayHello (name1:String, _ name2:String) {
        print("hello \(name1)");
        print("hello \(name2)");
    }
    sayHello("EndEvent", "Swift");
    输出结果: 
    hello EndEvent
    hello Swift
    
    • 默认参数值,即可以给函数体中每个参数定义默认值。如果有默认值,在调用的时候可以忽略此参数:
    // 参数style是有默认值的
    func goHome (name: String, style: String = "走路") {
        print("\(name)是\(style)回家的");
    }
    goHome("EndEvent");  // 可以忽略style参数
    goHome("Swift",style: "飞");
    goHome("liming", style: "开车");
    输出结果:
    EndEvent是走路回家的
    Swift是飞回家的
    liming是开车回家的
    

    注意: 将带有默认值的参数放在函数参数列表的最后,这可以保证在函数调用时,非默认参数的顺序的一致性,同时在相同函数在不同情况下调用时显得更为清晰。

    _ 可变参数,可变参数表示可以不接收或接收多个值。通过在变量类型们后加入...的方法来定义可变参数:

    // 计算平均值方式,参数是可变的
    func arithmeticMean(numbers:Int...) -> Float {
        var total:Float = 0;
        var sum = 0;
        for number in numbers {
            sum += number;
        }
        total = Float(sum) / Float(numbers.count);
        
        return total;
    }
    let total = arithmeticMean(1,2,3,4,5,6,7,8,9);
    print(total);
    输出结果: 5.0
    

    注意: 一个函数中最多只能有一个可变参数。

    • 常量参数和变量参数。函数参数默认是常量,试图在函数体重修改参数值这会导致编译出错。但有时候如果想修改参数值,那么久可以将参数定义为变量参数:
    func myAppend(var str:String) -> String {
        str.appendContentsOf(" --- haha");
        return str;
    }
    print(myAppend("EndEvent"));
    输出结果: EndEvent --- haha
    

    注意: 对于变量参数,在函数调用结束后便会消失,即是变量参数仅仅存在于函数调用的生命周期中。

    • 输入输出参数。如果想要在一个函数可以修改参数的值,并且在函数调用结束后仍然存在,即可以把这个参数定义为* 输入输出参数(In-Out Parameters) *
    // 值的交换
    func swapTwoInts(inout a:Int, inout b: Int) {
        let tempValue = a;
        a = b;
        b = tempValue;
    }
    // 定义两个变量,并初始化
    var a = 10;
    var b = 30;
    // 调用函数交换两个变量的值
    swapTwoInts(&a, b: &b);
    print("a = \(a)");
    print("b = \(b)");
    输出结果: a = 30    b = 10
    

    注意:输入输出参数和返回值不一样,其实这就是将变量的地址传过去,在函数体中通过变量的地址进行修改值。

    四、函数类型

    每个函数都有特定的函数类型,由函数的参数类型和返回值类型组成。

    • 使用函数类型。在swift中,使用函数类型就像使用其他类型一样:
    // 相加函数
    func sumFunc(a:Int, b:Int) -> Int {
        return a + b;
    }
    // 相乘函数
    func mathFunc(a:Int, b:Int) -> Int {
        return a * b;
    }
    // 定义变量str,类型为(Int,Int) -> Int
    var str:(Int,Int) -> Int = sumFunc;      
    // 调用相加函数
    print("10 + 20 = \(str(10, 20))");
    // 给str这个变量赋值一个函数
    str = mathFunc;
    // 调用相乘函数
    print("10 * 20 = \(str(10, 20))");
    输出结果: 10 + 20 = 30    10 * 20 = 200
    
    • 函数类型作为参数类型。即你可以将(Int, Int) -> Int这样的函数类型作为另外一个函数的参数类型:
    // 相乘函数
    func mathFunc(a:Int, b:Int) -> Int {
        return a * b;
    }
    // 输出函数
    func printMathFuncResult(mathFunc:(Int, Int) -> Int, a:Int, b:Int){
        print("\(a) * \(b) = \(mathFunc(a,b))");
    }
    // 调用输出函数
    printMathFuncResult(mathFunc, a: 10, b: 10);
    输出结果: 10 * 10 = 100
    

    注意: 可能认为这和函数调用效果是一样,现在这是否多此一举?其实不是,printMathFuncResult (:::)函数作用是输出另外一个适当类型的数学函数的调用结果。即在这里只关心传入的函数类型是否正确,而不在意函数如何实现。printMathFuncResult (:::)就是以一种安全类型(type-safe)的方式,将部分功能转给调用者实现,也即是方便代码的封装。

    • 函数类型作为返回类型。可以将函数类型作为另外一个函数的返回类型:
    // 实现功能: 将currentInput值变为0的过程
    var currentInput = -5;
    // 加操作
    func stepForward(input:Int) -> Int {
        return input + 1;
    }
    // 减操作
    func stepBackward(input:Int) -> Int {
        return input - 1;
    }
    // 函数选择,参数为input,返回值为'(Int) -> Int'类型
    func chooseStepFunction(isBackward:Bool) -> (Int) -> Int {
        // YES:即表示currentInput值是大于0的,选择stepBackward减操作
        // NO: 即表示currentInput值是小于0的,即选择stepForward加操作
        return isBackward ? stepBackward : stepForward;
    }
    // 循环操作,直到currentInput为0
    while currentInput != 0 {
        print("currentInput: \(currentInput)");
        // 根据currentInput值,选择对应操作的函数
        var moveNearerToZero = chooseStepFunction(currentInput > 0);
        // 调用操作
        currentInput = moveNearerToZero(currentInput);
    }
    print("结束操作:\(currentInput)");
    输出结果:
    currentInput: -5
    currentInput: -4
    currentInput: -3
    currentInput: -2
    currentInput: -1
    结束操作:0
    

    五、嵌套函数

    • 在本节文章中你说见到函数都是* 全局函数(global functions) ,它们都是属于全局域的。但你也可以将函数定义在函数体中,而这种称之为 嵌套函数(nested functions) 。
    • 嵌套函数 ,在默认情况下对外界是不可见的,但却可以被它们的 外围函数(enclosing function) *调用。并且外围函数也可以返回其所嵌套的函数,使得这个函数也可以在其他域中被调用。
    // 实现功能: 输入一个值,将值变为0的过程
    var currentInput = -5;
    // 函数选择 - 全局函数
    func chooseStepFunction(isBackwark:Bool) -> (Int) -> Int {
        // 加操作 - 嵌套函数
        func stepForward(input:Int) -> Int {
            return input + 1;
        }
        // 减操作 - 嵌套函数
        func stepBackward(input:Int) -> Int {
            return input - 1;
        }
        
        return isBackwark ? stepBackward : stepForward;
    }
    // 即是接受'(Int) -> Int' 类型的函数
    let moveNearerToZero = chooseStepFunction(currentInput > 0);
    // 循环操作,直到currentInput为0
    while currentInput != 0 {
        print("currentInput: \(currentInput)");
        currentInput = moveNearerToZero(currentInput);
    }
    print("结束操作:\(currentInput)");
    输出结果:
    currentInput: -5
    currentInput: -4
    currentInput: -3
    currentInput: -2
    currentInput: -1
    结束操作:0
    

    注:xcode7.3环境
    作者:西门奄
    链接:https://www.jianshu.com/u/77035eb804c3
    來源:简书
    简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

    相关文章

      网友评论

          本文标题:04-Swift函数(Functions)

          本文链接:https://www.haomeiwen.com/subject/vpumzftx.html