元类
1.runtime
runtime
,直译过来是运行时,它是一套底层的C语言API,包含很多强大实用的C语言数据类型和C语言函数。我们的OC代码在运行阶段都是基于runtime环境才能正常运行的。
2.常用场景
- 发送消息;
- 读取成员变量;
- 动态为某个类增加属性;
- 交换类中的方法、动态为某个类添加方法;
- 动态创建、删除、修改一个类;
3.对象
OC中,含有isa指针且该指针可以正确指向类的数据结构,都可以视为对象。
下面是objc.h
中的相关定义:
#if !OBJC_TYPES_DEFINED
/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;
/// Represents an instance of a class.
struct objc_object {
Class isa OBJC_ISA_AVAILABILITY;
};
/// A pointer to an instance of a class.
typedef struct objc_object *id;
#endif
从objc_object
结构体的定义可以看出:对象实质上是一个结构体,其结构体内含有isa
指针,指向其所属的类。
4.类
下面是runtime.h
中对类
的定义:
struct objc_class {
Class isa OBJC_ISA_AVAILABILITY; //指针
#if !__OBJC2__
Class super_class //父类;
const char *name //类名;
long version //类的版本信息,默认为0;
long info //位标识;
long instance_size //类的实例变量大小;
struct objc_ivar_list *ivars //类的成员变量链表;
struct objc_method_list **methodLists //方法定义的链表;
struct objc_cache *cache //方法缓存;
struct objc_protocol_list *protocols //协议链表;
#endif
} OBJC2_UNAVAILABLE;
从结构体的定义来看,类也是以isa
开始并指向类的数据结构。OC中类与元类在运行时都是objc_class
类型,所以,类和元类也是一种对象。
5.元类
1 |
|
5.1.实例对象
实例对象
,instance object,是指从某个类实例化而来的对象,如示例中的obj
。
5.2.类对象
类对象
,Class object,是指类作为对象时,称之为类对象。调用一个 “类方法” ,如 [NSObject alloc],实质上是向它的类对象(NSObject)发送了一个消息。类对象是由编译器创建的,任何继承自NSObject的类,它的实例对象中都有一个isa指针,指向它的类对象。
5.3.元类
元类
,Metaclass,是类对象
的isa指针所指向的类,类对象是元类的实例。
区分类对象与元类:
- 类对象中保存的是关于其实例对象的信息(变量,实例方法、遵守的协议等);
- 元类中保存的是关于类的信息(类方法,类的版本,名字等);
借用网上的一张图,演示元类与继承的封闭循环:
图中实线是 super_class 指针,虚线是isa
指针。
- 实例对象是类的实例;
- 类作为对象又是元类的实例;
- 元类作为对象是根元类的实例;
- 根元类是其自身的实例;
- 根类的 superclass 为 nil;
- 根元类的 superclass 为根类自己;
6.isa
isa 等价于 is kind of:
- 实例对象的 isa 指向类对象;
- 类对象的 isa 指向元类对象;
- 元类对象的 isa 指向根元类;
- 根元类对象的 isa 指向其自身;
7.相关函数
1 |
|
对于实例对象,返回其 isa 指针指向的类
;对于类对象,返回其本身
。
1 |
|
返回isa指针指向的内容。对实例对象,返回其 isa 指向的类
;对类对象,返回其对应的元类
。
1 |
|
返回对应的元类
。
相关参考:
元类
https://davidlii.cn/2017/08/22/runtime-metaclass.html