Category场景、继承与多态

2019-07-12  本文已影响0人  厨子

实例变量 = 成员变量 = ivar

category使用场景

  1. 为源码文件添加方法
  2. 按功能进行分类,放到多个文件中
  3. 第二点带来的好处:减小单个文件大小、方便多人开发同一个类、按需加载需要的 category

可以参考苹果的 UIKit 库中,就使用了很多的 category

category不可为

typedef struct category_t {
    const char *name;  //类名
    classref_t cls;         
    struct method_list_t *instanceMethods;  //category中添加的实例方法
    struct method_list_t *classMethods;       //category中添加的类方法
    struct protocol_list_t *protocols;             //category实现的协议
    struct property_list_t *instanceProperties;  //category中添加的属性
} category_t;

从结构体中看,category 可以添加实例方法类方法协议属性,但不可添加实例变量(带下划线的实例变量)

由于 @property的本质是

@property = ivar(实例变量) + getter + setter;

而在 category 中使用 @property 声明的属性,并不会自动生成 gettersetter 方法,以及 _ivar(所以一般说 category 不能声明属性). 当打点调用该属性时,编译没有问题(因为category是运行期决定),但运行起来走到调用的地方,必定报错:

[XXX xx]: unrecognized selector sent to instance X

Extension

Extension 通常存在于某个类的 .m 文件中,以下面的形式存在

@interface ABC()
///属性和方法声明
@end

也可以单独创建一个Extension 文件(只有.h),该文件可以通过下面步骤创建:
新建文件->Object-C文件->文件类型选 Extension -> 然后选择所属的类

Extension 可以声明方法属性实例变量

Category 与 Extension区别

  1. Extension 可以添加实例变量Category不可以,因为在运行期,对象的内存布局已经确定,如果添加实例变量会破坏类的内部布局,这对编译性语言是灾难性的
  2. Extension 在编译期决定,Category 在运行期决定怎么生成属性方法等
  3. 只能为源码文件添加 Extension,添加 Category 不需要知道源码文件

继承与多态

OC中的继承是单继承。即一个类至多只能有一个父类。子类继承父类的属性和方法,子类可以重写父类的方法。

多态 借助于动态绑定:动态类型能使程序直到运行时才确定对象所属的类型。动态类型绑定能使程序直到运行时才确定对象要调用的方法

在模拟多态的场景,需要两个条件:
- 继承
- 父类指针接收子类的对象

使用父类指针接收子类对象,可以带来两个好处:
- 该指针对象可以调用父类的所有方法和属性
- 如果该指针对象调用了子类的方法和属性,也不会引起报错,如果反过来了,子类指针接收了父类对象,那么当调用子类的方法或属性时,必定报错

因此,由于多态的存在,在编写程序时,如果不知道某个参数具体是哪个子类类型,那么,可以把该参数类型统一写成其父类的类型,接收后,再判断能调用哪些方法或属性。

上一篇下一篇

猜你喜欢

热点阅读