本文章将记录Objective-C中实例对象、类对象、元类对象的相关资料,如有错误欢迎指出~
实例对象(InstanceObject)
实例对象是类实例化的对象,代表着某一个具体的东西。在OC中表现为:
Person *man = [Person new];
Person是类, man就是Person实例化的对象,代表着一个具体的东西,即男人。
实例对象是我们对类对象alloc或者new操作时所创建的,在这个过程中会拷贝实例所属的类的成员变量,但并不拷贝类定义的方法。调用实例方法时,系统会根据实例的isa指针去类的方法列表及父类的方法列表中寻找与消息对应的selector指向的方法。我们来看下其定义:
/// Represents an instance of a class.
struct objc_object {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
};
这个结构体只有一个isa变量,指向实例对象所属的类。任何带有以指针开始并指向类结构的结构都可以被视作objc_object, 对象最重要的特点是可以给其发送消息。
类对象(Class)
类对象是由程序员定义并在运行时由编译器创建的,它没有自己的实例变量,这里需要注意的是类的成员变量和实例方法列表是属于实例对象的,但其存储于类对象当中的。我们看看Class的定义:
/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;
可以看到类是由Class类型来表示的,它是一个objc_class结构类型的指针。我们接着来看objc_class结构体的定义:
struct objc_class {
Class isa; // 指向所属类的指针(_Nonnull)
Class super_class; // 父类
const char *name; // 类名(_Nonnull)
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; // 协议链表
};
isa指针是和Class同类型的objc_class结构指针,类对象的指针指向其所属的类,即元类。元类中存储着类对象的类方法,当访问某个类的类方法时会通过该isa指针从元类中寻找方法对应的函数指针
super_class为该类所继承的父类对象,如果该类已经是最顶层的根类(如NSObject或NSProxy), 则 super_class为NULL
ivars是一个指向objc_ivar_list类型的指针,用来存储每一个实例变量的地址
-
info为运行期使用的一些位标识,比如:
CLS_CLASS (0x1L)表示该类为普通类, CLS_META (0x2L)则表示该类为元类
methodLists用来存放方法列表,根据info中的标识信息,当该类为普通类时,存储的方法为实例方法;如果是元类则存储的类方法
cache用于缓存最近使用的方法。系统在调用方法时会先去cache中查找,在没有查找到时才会去methodLists中遍历获取需要的方法
元类对象(Metaclass)
元类就是类对象的类,每个类都有自己的元类,也就是objc_class结构体里面isa指针所指向的类. Objective-C的类方法是使用元类的根本原因,因为其中存储着对应的类对象调用的方法即类方法。
所以由上图可以看到,在给实例对象或类对象发送消息时,寻找方法列表的规则为:
- 当发送消息给实例对象时,消息是在寻找这个对象的类的方法列表(实例方法)
- 当发送消息给类对象时,消息是在寻找这个类的元类的方法列表(类方法)
元类,就像之前的类一样,它也是一个对象,也可以调用它的方法。所以这就意味着它必须也有一个类。所有的元类都使用根元类作为他们的类。比如所有NSObject的子类的元类都会以NSObject的元类作为他们的类。
根据这个规则,所有的元类使用根元类作为他们的类,根元类的元类则就是它自己。也就是说基类的元类的isa指针指向他自己。
为了更好的理解对象,类对象、元类的关系,可以参考下面这幅图:
总结一下实例对象,类对象以及元类对象之间的isa指向和继承关系的规则为:
- 实例对象的isa指向该类,类的isa指向元类(metaClass)
- 类的superClass指向其父类,如果该类为根类则值为nil
- 元类的isa指向根元类,如果该元类是根元类则指向自身
- 元类的superClass指向父元类,若根元类则指向该根类