美文网首页
swift基础——函数

swift基础——函数

作者: 夜凉听风雨 | 来源:发表于2022-03-09 20:08 被阅读0次

    函数分类

    • 无参无返

    下面三种方式都可以
    Void在swift里的定义就是空元组()

    func say() -> Void {
        print("hello")
    }
    
    func say() -> () {
        print("hello")
    }
    
    func say() {
        print("hello")
    }
    
    
    • 无参有返
    func pi() -> Double {
        return 3.14
    }
    
    • 有参无返
    func say(text:String) {
        print(text)
    }
    
    • 有参有返

    函数的形参是let,也只能是let

    func add(a:Int, b:Int) -> Int {
        return a + b
    }
    

    隐式返回

    如果整个函数体是一个单一表达式,那么函数会隐式返回这个表达式

    func add(a:Int, b:Int) -> Int {
        a + b // 可以省略return
    }
    
    let sum = add(a: 10, b: 20)
    print(sum) // 打印: 30
    

    函数的文档注释

    注释及其效果.png

    参数标签

    可以修改参数标签,这样的目的是为了让函数调用的时候,更像是一个完整的英文句子,更好理解函数的意思。

    func goToWork(at time:String) {
        print("time is \(time)")
    }
    
    goToWork(at: "8:00") // 很像 go to work at 8:00
    

    可以使用下划线_省略参数标签,不过不建议这么使用

    func add(_ a:Int, _ b:Int) -> Int {
        return a+b
    }
    add(10, 20) 
    

    默认参数值

    可以在声明方法的时候,为参数设置一个默认值,当方法调用时没传入该参数时,该参数值为默认值。

    func check(name: String = "Jonas", age: Int, job: String = "none") {
        print("name=\(name),age=\(age),job=\(job)")
    }
    
    check(age: 15) // name=Jonas,age=15,job=none
    check(name: "Bob", age: 20, job: "Doctor") // name=Bob,age=20,job=Doctor
    check(name: "Mary", age: 18) // name=Mary,age=18,job=none
    check(age: 30, job: "postman") // name=Jonas,age=30,job=postman
    

    可变参数

    在参数类型后面加...表示可以传入不等数量的参数,相当于是一个数组

    • 一个函数最多只能有一个可变参数
    func countNumber(numbers: Int...) {
        print(numbers) // [1,2,3,4,5]
    }
    countNumber(numbers: 1,2,3,4,5)
    
    • 紧跟在可变参数后面的参数不能省略参数标签

    下面的例子在可变参数numbers后面的是student参数,它不能使用下划线来省略参数标签。

    func countNumber(numbers: Int..., student: String, _ age: Int) {
        print(numbers) // [1,2,3,4,5]
    }
    
    countNumber(numbers: 1,2,3,4,5, student: "Bob", 15)
    

    输入输出参数(In-Out-Parameter)

    • 可以用inout定义一个输入输出参数:可以在函数内部修改外部实参的值
    • 输入输出参数在传参时要加 &
    • 可变参数不能标记为输入输出参数
    • inout参数不能有默认值
    • inout参数的本质是地址传递(引用传递)
    • inout参数只能传入可以被多次赋值的
      let修饰的常量就不可以,或者直接传一个字面量也不可以。
    func change(num: inout Int) {
        num = 20
    }
    
    var number = 10
    change(num: &number)
    print(number) // 20
    

    函数重载

    重载的函数可以和原函数共存,虽然有多个名字一样的函数,但是也可以根据情况不同调用不同的函数。

    • 规则
      1、函数名相同
      2、参数个数不同 || 参数类型不同 || 参数标签不同
    函数重载示例.png 调用重载函数.png
    • 返回值类型不构成重载
      下图所示两个方法只有返回值类型不同,但是不构成重载,调用会报错。
    返回值重构问题.png
    • 默认参数值和函数重载一起使用产生二义性时,编译器并不会报错(在C++中会报错)
    默认参数值重构问题.png
    • 可变参数、省略参数标签、函数重载一起使用产生义性时编译器有可能会报错
    可变参数省略参数标签重载.png

    内联函数

    • 如果开启了编译器优化( Release模式默认会开启优化) , 编译器会自动将某些函数变成内联函数
      将函数调用展开成函数体
    编译器优化配置.png
    • 哪些函数不会被内联?
      1、函数体比较长:函数体太长如果内联,多次调用会增大汇编代码数量
      2、包含递归调用:会导致死循环
      3、包含动态派发:在编译时无法确定调用方法

    @inline

    // 永远不会内联,即使开启了编译器优化
    @inline(never) func test() {
        print("hello")
    }
    
    // 开启编译器优化后,即使函数内的代码很多,也会被内联(递归调用函数,动态派发的函数除外)
    @inline(__always) func test() {
        // ...很多的代码
    }
    

    release模式下,编译器开启优化,会自动决定内联函数,所以这个@inline也基本不用。

    函数类型

    • 每一个函数都是有类型的,函数类型由形式参数类型、返回值类型组成
    func method() {} // 函数类型:() -> Void 或者() -> ()
    
    func add(a: Int, b: Int) -> Int {
        return a + b
    } // 函数类型:(Int, Int) -> Int
    
    • 使用函数类型,可以定义变量
    func method() {} // 函数类型:() -> Void 或者() -> ()
    
    func add(a: Int, b: Int) -> Int {
        return a + b
    } // 函数类型:(Int, Int) -> Int
    
    var fn : (Int, Int) -> Int = add
    fn(10, 20) // 30 调用时不需要参数标签
    
    • 使用函数类型,可以作为参数类型
    func add(a: Int, b: Int) -> Int {
        return a + b
    } // 函数类型:(Int, Int) -> Int
    
    func printResult(mathFn: (Int, Int) -> Int, a: Int, b: Int) {
        let result = mathFn(a, b)
        print(result)
    }
    
    printResult(mathFn: add, a: 20, b: 30) // 50
    
    • 函数类型作为函数返回值
      返回值是函数类型的函数,叫做高阶函数
    func add(num: Int) -> Int {
        return num + 1
    }
    
    func reduce(num: Int) -> Int {
        return num - 1
    }
    
    func select(result: Bool) -> (Int) -> Int {
        return result ? add : reduce
    }
    
    // select返回的是add函数
    select(result: true)(10) // add函数传入10结果为11
    

    typealias

    typealias用来给类型起别名

    // 为一个元组起别名为DateType
    typealias DateType = (year: Int, month: Int, day: Int)
    
    func method(date: DateType) {
        print("今天是\(date.year)年\(date.month)月\(date.day)日")
    }
    method(date: (2022, 3, 10)) // 今天是2022年3月10日
    
    // 为一个函数类型起别名为fnType
    typealias fnType = (Int, Int) -> Int
    
    func add(a: Int, b: Int) -> Int {
        a + b
    }
    
    let method : fnType = add
    method(10, 20) // 30
    

    嵌套函数

    • 将函数定义在函数内部
      嵌套函数可以将内部的函数隐藏起来,不让外部直接调用
    func selectMethod(result: Bool) -> (Int, Int) -> Int {
        func add(a: Int, b: Int) -> Int {
            a + b
        }
        
        func reduce(a: Int, b: Int) -> Int {
            a - b
        }
        
        return result ? add : reduce
    }
    
    let fn = selectMethod(result: true) // add
    fn(10, 20) // 30
    

    相关文章

      网友评论

          本文标题:swift基础——函数

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