实例变量 = 成员变量 = ivar
category使用场景
- 为源码文件添加方法
- 按功能进行分类,放到多个文件中
- 第二点带来的好处:减小单个文件大小、方便多人开发同一个类、按需加载需要的
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
声明的属性,并不会自动生成 getter
、setter
方法,以及 _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区别
-
Extension
可以添加实例变量
,Category
不可以,因为在运行期,对象的内存布局已经确定,如果添加实例变量会破坏类的内部布局,这对编译性语言是灾难性的 -
Extension
在编译期决定,Category
在运行期决定怎么生成属性方法等 - 只能为源码文件添加
Extension
,添加Category
不需要知道源码文件
继承与多态
OC中的继承是单继承。即一个类至多只能有一个父类。子类继承父类的属性和方法,子类可以重写父类的方法。
多态 借助于动态绑定:动态类型能使程序直到运行时才确定对象所属的类型。动态类型绑定能使程序直到运行时才确定对象要调用的方法
在模拟多态的场景,需要两个条件:
- 继承
- 父类指针接收子类的对象
使用父类指针接收子类对象
,可以带来两个好处:
- 该指针对象可以调用父类的所有方法和属性
- 如果该指针对象调用了子类的方法和属性,也不会引起报错,如果反过来了,子类指针接收了父类对象,那么当调用子类的方法或属性时,必定报错
因此,由于多态的存在,在编写程序时,如果不知道某个参数具体是哪个子类类型,那么,可以把该参数类型统一写成其父类的类型,接收后,再判断能调用哪些方法或属性。
网友评论