反射是编程语言中一项强大的能力:
- 对于任意一个类型,能动态获取这个类的所有属性、方法信息。
- 对于任意实例,能动态调用它的任意方法和属性。
一、Swift中的反射功能
Swift
中目前通过Mirror
来实现反射功能。
func testMirror() {
let mirror = Mirror(reflecting: ZLCar())
// 展示类型:`struct`、`class`、`enum`、tuple、optional、collection、dictionary、set
// 闭包的mirror.displayStyle是nil
print(mirror.displayStyle!)
// 类型名:这里是ZLCar
print(mirror.subjectType)
// 可以通过children属性来获取内部的子结构
print(mirror.children)
for pro in mirror.children {
// 属性名,属性值
print("\(pro.label): \(pro.value)")
}
// 对象父类的mirror
print(mirror.superclassMirror)
}
二、Swift中的消息派发方式
1. 直接派发
- 全局函数
- 使用static声明的方法
- 使用final声明的所有方法,使用final声明的类里面的所有方法
- 使用private声明的方法和属性,会隐式final声明
- 值类型的方法,比如struct和enum中的方法
- 在extension中没有使用@objc修饰的实例方法
2. 函数表派发
- 只有引用类型才是函数表派发
- 在Swift中,类的方法默认使用函数表派发的方式
- Swift对于协议Protocol默认使用的是函数表派发,协议可以为struct提供多态的支持
- Swift的函数表叫做 witness table(C++叫做virtual table)
1.每个子类都有自己的表结构
2.对于类中每个重写的方法,都有不同的函数指针
3.当子类添加新方法时,这些方法指针会添加到函数表的末尾
4.在运行时使用此表来调用函数的实现 (函数表指针 + 函数偏移 就能找到对应的方法)
3. 消息派发
- 用dynamic修饰的方法是消息派发。
- 对于继承自NSObject的Swift类,消息派发方式。
注意: @objc修饰方法,只是把方法暴露给objc,是函数表派发
想了解更多可以阅读文章
反射 Mirror | Swift 动态性
网友评论