1. 函数类型
之前在代码的书写过程中,我们已经或多或少的接触过函数,函数本身也有自己的类型,它由形式参数类型,返回类型组成。如果将函数传递给a变量,那么就可以借助a来调用方法,这里addTwoInts代表函数类型。如果出现了同名函数,但是返回值或者参数不一样,那么就需要指明函数类型。否则就会报 ambiguous user of *** 错误,因为这个时候编译器不知道要给a赋值哪一个参数。把函数赋值给a,那么a里面储存的是什么呢?
运行后打印a,这里看懂存储的是函数类型.这里函数类型也是引用类型,当把函数赋值给a的时候,就把函数的metadata赋值给了a.
这里打印b,看到了存储的信息是一样的,证明了函数类型是引用类型。
到源码中查看函数的metadata,之前的学习中可以知道,直接搜索名字functiontype,就找到了函数在源码中的结构体。看到其继承自TargetMetadata,那么就会有kind,也就是oc中的isa。其次还有flags。
flags的类型点进去可以看到看到这里有enum,这些关键字标注了函数的类型。
函数类型里面还有一个ResultType,也就是返回值类型。最后就是参数了,这里看到是用连续的内存空间存放参数,读取参数是用getParameters方法读取。
模仿出function的结构体,这里flags与上掩码可以得到有多少个参数。
那么这里就可以使用unsafeBitCast将函数转换为TargetFunctionTypeMetadata结构体,然后调用numberArguments方法看到有几个参数了。
2. 闭包
闭包是一个捕获了上下文的常量或者是变量的函数,即使常量或者变量的作用域已经不在,闭包仍然可以修改他们。当每次修改捕获值的时候,其实是修改堆区的值。闭包中没有block哪有全局,堆,栈的概念了。
在函数makeIncrementer里面定一个函数incrementer,incrementer里面使用了外部函数的变量runningTotal。当调用makeIncrementer() 复制给a的时候
,明显的可以知道incrementer的生命周期比makeIncrementer要长,而runningTotal是属于外部函数的变量,外部函数返回之后,外部函数就消失了,而内部函数要想使用runningTotal,那么就必须把runningTotal捕获到incrementer的内部,这样才能在使用incrementer的使用,正确使用runningTotal的值,incrementer和匹配的runningTotal的变量,构成了闭包。