OC语言的动态性
OC语言的动态性主要体现在以下3各方面:
- 动态类型:运行时确定对象的类型。
- 动态绑定:运行时确定对象的调用方法。
- 动态加载:运行时加载需要的资源或者可执行代码。
1.动态类型
动态类型指对象指针类型的动态性,具体是指使用id类型将对象的类型推迟到运行时才确定,由赋给它的对象类型决定对象指针的类型。另外,类型确定推迟到运行时之后,可以通过NSObject的isKindOfClass方法动态判断对象最后的类型(动态类型识别)。也就是说,id修饰的对象为动态类型的对象,其他在编译期指明类型的为静态类型对象,通常如果不需要涉及多态还是要尽量使用静态类型(原因:错误可以在编译期提前查出,可读性好)。
2.动态绑定
动态绑定指方法确定的动态性,建立在动态类型的物质基础之上,具体指在OV的消息分发机制下将要执行的方法推迟到运行时才确定,可以动态添加方法。也就是说,一个OC对象是否调用某个方法不是编译期决定的,方法的调用不和代码绑定在一起,而是到了运行时根据发出的具体消息而动态确定要调用的代码。
动态绑定是基于动态类型的,在运行时对象的类型确定后,对象的属性和方法也就确定了,包括类中原来的属性和方法,以及运行时动态新加入的属性和方法。
3.动态加载
动态加载主要包含2个方面,一个是资源动态加载,另一个是代码模块的加载。这些资源在运行时根据需要有选择地加入到程序中,是一种代码和资源的“懒加载”模式,可以降低内存开销,提高整个程序的性能,另外也大大提高了可扩展性。
4扩展
4.1OC中的id类型指什么?id、ni l代表什么?
id表示OC对象的类型在编写代码时(编译时)不确定,视为任意Object类型,知道程序运行时才最终确定其类型。
id类似于C/C++的void *,但id和void 并非完全一样。id是一个指针,虽然省略了。id和void *之间需要通过bridge关键字来显示地桥接转换。
id nsobj = [[NSObject alloc] init];
void *p = (__bridge void *)nsobj;
id obj = (__bridge id)p;
4.2instancetype和id有什么区别?
instancetype和id都可以表示任意类型,将对象类型的确定往后推迟,用于体现OC语言的动态性。
区别是:instancetype只能作为返回值类型,且在编译时instancetype会进行类型检测,因此对于所有实例方法或者类方法,返回类型全部用instancetype。id类型既可以做为返回值类型,也可以作为参数类型,也可以做为变量的类型,但id类型在编译期不会进行类型检测。
4.3id,NSObject,id<NSObject>的区别是什么?
NSObject修饰的对象肯定是NSObject对象,但id修饰的对象肯定是OC对象但不一定是NSObject对象。id类型是一种运行时的动态类型,编译器不会对齐进行类型检查。id<NSObject>修饰的对象也是一种动态类型的对象,运行时才确定,但编译器知道它一定遵守NSObject协议。