Function (swift)

2018-05-30


import UIKit

class FunctionController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        //1 调用 实参传入的是空元组
        voidFunc(v: ())
        //2 调用
        function(label: 10, label: 10)
        //3 调用 (注意 编译错误: 缺失了第二个形参的实参)
//        oops(10)
        //4 调用
        // 不传任何不定个数形参所对应的实参
        foo(a: 0)
        // 传了1个不定个数形参所对应的实参
        foo(a: 0, b: 1)
        // 传了3个不定个数形参所对应的实参
        foo(a: 0, b: 1,2,3)
        //5 调用
        var b: Int! = nil
        var c: Int! = 5
        poo(a: &b)
        poo(a: &c)
        print("b = \(b)")
        print("c = \(c)")
        //6 调用
        (foo as (Int?) -> Void)(2)
        let _: Int = foo(2)
    }
    
    //1 定义一个具有Void类型形参返回类型为Void的函数
    func voidFunc(v: Void) -> () {
        
    }
    
    //2 定义 实参可相同,形参必须不同
    func function(label p1: Int, label p2: Int) {
        print("parameter is: \(p1 + p2)")
    }
    
    //3 定义 实参都缺省且中间的参数不带默认值
    func oops(_ a: Int = 1, _ b: Int, _ c: Int = 2) {
        
    }
    
    //4 定义一个带有Int类型的不定参数个数的函数foo
    func foo(a: Int, b: Int...) {
        
        var sum = a
        
        if b.count > 0 {
            for i in b {
                sum += i
            }
        }
    }
    
    //5 定义一个Int!输入输出参数类型的函数
    func poo(a: inout Int!) {
        
        if a == nil {
            a = 0
        }else {
            a! += 10
        }
    }
    
    //6 定义两个重载函数(返回类型不同)
    func foo(_ c: Int?) {
        print("foo c = \(String(describing: c))")
    }
    
    func foo(_ g: Int?) -> Int {
        return g ?? 0
    }
}


  • (1) 函数定义与调用
    /// func 函数名 (函数形参列表) -> 返回类型 {函数体}
    /// swift 的 形参类型 与 返回类型 可以是swift所支持的任一类型,数组,元组...
  • (2) 函数的实参/形参标签
    /// 实参标签名可以相同 形参标签名必须各不相同
    /// 实参可缺省 形参如函数体内不使用也可缺省 用通配符 _
    /// 从swift4.0起,调用形参类型为Void类型的函数时,对应的实参必须显示传入空元祖,即()
  • (3) 默认形参值 (无需放在形参列表的最后,跟c++不同)
    /// 在调用一个带有默认形参值得函数时,倘若使用该新参的默认值,那么连它的实参标签都不需要写,实参标签加上实参值全都缺省
  • (4) 不定个数的形参(无需放在形参列表的最后)
    /// ...前面跟一个类型
    /// 可以把它视作为它所指定类型的数组 通过count属性获取实参所传递过来的参数个数,通过下表操作符来获取对应的实参值
  • (5) 输入输出形参 in-out parameters
    /// 在swift中,所有新参默认都是常量
    /// 当我们调用一个函数时,对其中某一个输入输出形参传递了某个实参,在该函数内会做以下三步:
    /// 1,当函数在调用前,先将实参的值拷贝到所对应的输入输出形参中
    /// 2, 在执行函数中的代码时,对输入输出形参的值进行修改
    /// 3, 在函数返回之后,将修改后输入输出形参的值拷贝回对应的实参中
    /// 关键字 in-out 仅仅只是个类型限定符,用于描述当前形参在该函数体内可被修改而已
    /// “而在调用函数时,我们在表示实参的表达式之前加上 & 单目前缀操作符,表示该实参将会在函数返回后被所对应的形参进行赋值。 单目前缀操作符 & 的操作数必须是一个变量,而不能是一个常量”
    /// 输入输出参数类型的匹配比一般的要求更为严苛,inout Int! 与 inout Int? 作为不兼容的参数类型
  • (6) 函数重载
    /// 函数重载的判断依据为形参个数、形参类型以及函数的返回类型,其实还有实参标签的区别(这个跟函数签名有关)
    /// 如果仅仅是函数返回类型不同,那么调用的时候难以判别当前所调用的是哪个函数,因此需要使用as投射操作符将函数标识显示转换为特定的函数类型进行调用;或者对左值对象显式标注类型来告诉编译器,此时应该调用哪个类型的函数。不过,为了避免这种麻烦,一般使用不同的实参标签来更好得加以区分
  • (7) 函数类型与函数签名 (理解好概念) (1: 函数引用对象相关概念 2: 函数签名表达式相关概念)
    /// 1 声明一个函数引用对象的时候,其函数形参类型不能带有实参标签 (实际是声明)
    /// 1 调用一个函数引用对象的时候,它所指向的函数实体(实际是调用,就是函数签名表达式后面括号调用,即是实参不用了)已经是确定的了,所以不需要使用实参标签(也不允许给出),因为实参标签属于函数签名的一部分,用于标识一个特定的函数实体,而函数类型本身就是一个纯粹的类型,因此不需要,和带标签的元组不同。
    /// 1 而且这个指向函数的引用对象类型(实际也就是一个函数签名表达式)的函数形参中不能含有形参标签。
    /// (注意)一个指向函数的引用对象 与 其它类型的对象一样 闭包是引用类型。函数也是,跟类类型一样
    /// 2 一个函数签名表达式就已经表征了一个指向它所表示的函数的引用,所以该表达式的类型就是一个函数类型
    /// 2 在通过函数签名表达式去做函数调用时,也不需要显式给出实参标签,并且也不允许给出
    /// 2 严格意义上,两个具有不同函数签名的函数就已经表征了其不同的实体,(这里所描述的是实参标签不同或函数名不同,但是如果函数签名全都相同,那么再去判定那两个函数的类型)也就是用 as 投射操作符
  • 8 嵌套函数定义 (nested functions)
    /// 嵌套函数会持有外部函数的局部对象
    /// 嵌套函数不仅可以直接定义在函数体内,而且还能定义在语句块作用域内
  • 9 统一的函数引用体系
    /// 一个函数类型引用对象可以指向函数、闭包、实例方法三者任意一种

你可能感兴趣的:(Function (swift))