分类底层结构就是一个category_t
结构体,当我们每创建一个分类,系统编译时就会把这个分类转化成这样一个结构体保存起来。当我们在程序运行时,所有分类的这些属性方法等将会合并到类里面,分类的对象方法合并到类对象里面,分类的类方法合并到元类对象里面。合并进来的分类方法列表是放在数组的前面的,最后把所有分类的方法列表合并到原有类的方法列表前面,也就是说后编译的分类数据会在数组的前面,当我们调用时会优先调用数组前面的方法,不管类何时编译,只要它有分类就会把分类的方法列表合并到类的方法列表前面,所以我们调用时分类会覆盖类的方法
OC
的类可以多重继承么?可以实现多个接口么?Category
是什么?重写一个类的方式用继承好还是分类好?为什么?
OC
的类不可以多重继承;可以实现多个接口,通过实现多个接口可以完成C++
的多重继承;Category
是类别,一般情况用分类好,用Category
去重写类的方法,仅对本Category
有效,不会影响到其他类与原有类的关系
Category
(分类),Extension
(扩展)和继承的区别
1.分类
category
原则上只能在现有类基础上添加新的方法(能添加属性的原因只是通过runtime
解决无setter/getter
的问题而已),类别中的方法没被实现编译器是不会有任何警告的,这是因为类别是在运行时添加到类中的 2.扩展iOS
中的extension
就是匿名的分类,只有头文件没有实现文件。类扩展不仅可以增加方法,还可以增加实例变量(或者属性),只是该实例变量默认是@private
类型的(使用范围只能在自身类,而不是子类或其他地方),类扩展中声明的方法没被实现,编译器会报警,这是因为类扩展是在编译阶段被添加到类中的 3.继承 在iOS
中继承是单继承,既只能有一个父类。在继承中,子类可以使用父类的方法和变量,当子类想对本类或者父类的变量进行初始化,那么需要重写init()
方法 。父类也可以访问子类的方法和成员变量
Category
的实现原理,以及Category
为什么只能加方法不能加属性
分类的实现原理是将
category
中的方法、属性、协议数据放在category_t
结构体中,然后将结构体内的方法列表拷贝到原有类信息中。Category
可以添加属性,但是并不会自动生成成员变量及set/get
方法。因为category_t
结构体中并不存在成员变量。通过之前对对象的分析我们知道成员变量是存放在实例对象中的,并且编译的那一刻就已经决定好了。而分类是在运行时才去加载的。那么我们就无法在程序运行时将分类的成员变量添加到实例对象的结构体中。因此分类中不可以添加成员变量
Category
的加载处理过程
通过
Runtime
加载某个类的所有category
数据 把所有category
的方法、属性、协议数据合并到一个大数组中,后面参与编译的category
数据会在数组的前面 将合并后的分类数据(方法、属性、协议)插入到类原来数据的前面
Category
中有load
方法吗?load
方法是什么时候调用的?load
方法能继承吗
Category
中有load
方法,load
方法在程序启动装载类信息的时候就会调用。load
方法可以继承。调用子类的load
方法之前,会先调用父类的load
方法
load、initialize
的区别,以及它们在category
重写的时候的调用的次序
区别在于调用方式和调用时刻 调用方式:
load
是根据函数地址直接调用,initialize
是通过objc_msgSend
调用 调用时刻:load
是runtime
加载类、分类的时候调用(只会调用1次),initialize
是类第一次接收到消息的时候调用,每一个类只会initialize
一次(父类的initialize
方法可能会被调用多次) 调用顺序:先调用类的load
方法,先编译那个类,就先调用load
。在调用load
之前会先调用父类的load
方法。分类中load
方法不会覆盖本类的load
方法,先编译的分类优先调用load
方法。initialize
先初始化父类,之后再初始化子类。如果子类没有实现+initialize
,会调用父类的+initialize
(所以父类的+initialize
可能会被调用多次),如果分类实现了+initialize
,就覆盖类本身的+initialize
调用
- 用
runtime
可以实现分类添加成员变量,那这个成员变量是保存在哪里呢?是合并到类里面吗?
答案不是的。
runtime
为这个分类的关联对象单独进行管理,并不是合并到原有类里面。其实runtime
是生成一个AssociationsManager
类用来管理分类的关联对象,AssociationsManager
类有一个AssociationsHashMap
属性,这个属性相当于一个字典,用来存储对象-关联对象
的,它的key
是关联对象也就是这个分类,然后value
是一个ObjectAssociationMap
也相当于是一个字典,这个字典的key
是关联对象时传进去的那个key
,value
是ObjcAssociation
,里面有两个属性_value
和_policy
,这两个就是关联对象的值和关联策略