1. 函数类型
之前在代码的书写过程中,我们已经或多或少的接触过函数,函数本身也有自己的类型,它由形式参数类型,返回类型组成。如果将函数传递给a变量,那么就可以借助a来调用方法,这里addTwoInts代表函数类型。如果出现了同名函数,但是返回值或者参数不一样,那么就需要指明函数类型。否则就会报 ambiguous user of *** 错误,因为这个时候编译器不知道要给a赋值哪一个参数。把函数赋值给a,那么a里面储存的是什么呢?
func addTwoInts(_ a: Int, _ b: Int) -> Int { return a + b
}
var a = addTwoInts
a(10,20)
func addTwoInts(_ a: Double, _ b: Double) -> Double { return a + b
}
func addTwoInts(_ a: Int, _ b: Int) -> Int { return a + b
}
var a: (Double, Double) -> Double = addTwoInts
a(10, 20)
var b = a
b(20 ,30)
运行后打印a,这里看懂存储的是函数类型.这里函数类型也是引用类型,当把函数赋值给a的时候,就把函数的metadata赋值给了a.
这里打印b,看到了存储的信息是一样的,证明了函数类型是引用类型。
到源码中查看函数的metadata,之前的学习中可以知道,直接搜索名字functiontype,就找到了函数在源码中的结构体。看到其继承自TargetMetadata,那么就会有kind,也就是oc中的isa。其次还有flags。
flags的类型点进去可以看到看到这里有enum,这些关键字标注了函数的类型。
函数类型里面还有一个ResultType,也就是返回值类型。最后就是参数了,这里看到是用连续的内存空间存放参数,读取参数是用getParameters方法读取。
模仿出function的结构体,这里flags与上掩码可以得到有多少个参数。
那么这里就可以使用unsafeBitCast将函数转换为TargetFunctionTypeMetadata结构体,然后调用numberArguments方法看到有几个参数了。