iOS Runtime(一)------类和对象的本质

在面向对象的语言中,类和对象是我们接触最多的东西,那么在iOS中类和对象到底是什么样的?方法调用是怎么实现的?标题为Runtime,跟类和对象有什么关系呢?不要着急,跟着我的思路,开始认识iOS中类和对象的本质。
首先我们在中找到如下定义:

typedef struct objc_class *Class;
struct objc_object {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;
};
typedef struct objc_object *id;

中找到如下定义:

struct objc_class {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;

#if !__OBJC2__
    Class _Nullable super_class                              OBJC2_UNAVAILABLE;
    const char * _Nonnull name                               OBJC2_UNAVAILABLE;
    long version                                             OBJC2_UNAVAILABLE;
    long info                                                OBJC2_UNAVAILABLE;
    long instance_size                                       OBJC2_UNAVAILABLE;
    struct objc_ivar_list * _Nullable ivars                  OBJC2_UNAVAILABLE;
    struct objc_method_list * _Nullable * _Nullable methodLists                    OBJC2_UNAVAILABLE;
    struct objc_cache * _Nonnull cache                       OBJC2_UNAVAILABLE;
    struct objc_protocol_list * _Nullable protocols          OBJC2_UNAVAILABLE;
#endif

} OBJC2_UNAVAILABLE;

结合起来不难发现,类其实是就是一个指向结构体的指针,而对象其实就是一个指向struct objc_object的指针,它里面的isa指针指向他的类对象,引用网络上的一个图


通过这个图我们先大概的理解一下,对象```的```isa```指向其```类(或者叫类对象)```,```类isa指向元类,而元类的isa指向根元类根元类isa则指向自身
但是这张图仅仅是理论,那么实际是什么样子的呢?

Talk is cheap. Show me the code

废话不多说,上代码:

/**=======================================*/
@interface GrandFather:NSObject
@end
@implementation GrandFather
@end
/**=======================================*/
@interface Father:GrandFather
@end
@implementation Father
@end
/**=======================================*/
@interface Son:Father
@end
@implementation Son
@end

接下来我们来打印下细节(为了更加清晰,没有使用循环)

    Son *son = [[Son alloc] init];
    
    Class sonISA = object_getClass(son);
    Class sonClass = [sonISA class];
    
    Class sonClassISA = object_getClass(sonClass);
    Class sonClassClass = [sonClassISA class];
    
    Class sonClassClassISA = object_getClass(sonClassClass);
    Class sonClassClassClass = [sonClassClassISA class];
    
    Class sonClassClassClassISA = object_getClass(sonClassClassClass);
    Class sonClassClassClassClass = [sonClassClassClassISA class];
    NSLog(@"============Son Info============");
    NSLog(@"Son instance address:%p",son);
    
    NSLog(@"Son instance isa:%@------%p",NSStringFromClass(sonISA),sonISA);
    NSLog(@"Son Class:%@------%p",NSStringFromClass(sonClass),sonClass);
    NSLog(@"%@",class_isMetaClass(sonClass)?@"元类":@"非元类");
    
    NSLog(@"Son Class isa:%@------%p",NSStringFromClass(sonClassISA),sonClassISA);
    NSLog(@"Son Class Class:%@------%p",NSStringFromClass(sonClassClass),sonClassClass);
    NSLog(@"%@",class_isMetaClass(sonClassClass)?@"元类":@"非元类");
    
    NSLog(@"Son Class Class isa:%@------%p",NSStringFromClass(sonClassClassISA),sonClassClassISA);
    NSLog(@"Son Class Class Class:%@------%p",NSStringFromClass(sonClassClassClass),sonClassClassClass);
    NSLog(@"%@",class_isMetaClass(sonClassClassClass)?@"元类":@"非元类");
    
    NSLog(@"Son Class Class Class isa:%@------%p",NSStringFromClass(sonClassClassClassISA),sonClassClassClassISA);
    NSLog(@"Son Class Class Class Class:%@------%p",NSStringFromClass(sonClassClassClassClass),sonClassClassClassClass);
    NSLog(@"%@",class_isMetaClass(sonClassClassClassClass)?@"元类":@"非元类");
    
    Father *father = [[Father alloc] init];
    
    Class fatherISA = object_getClass(father);
    Class fatherClass = [fatherISA class];
    
    Class fatherClassISA = object_getClass(fatherClass);
    Class fatherClassClass = [fatherClassISA class];
    
    Class fatherClassClassISA = object_getClass(fatherClassClass);
    Class fatherClassClassClass = [fatherClassClassISA class];
    
    Class fatherClassClassClassISA = object_getClass(fatherClassClassClass);
    Class fatherClassClassClassClass = [fatherClassClassClassISA class];
    NSLog(@"============Father Info============");
    NSLog(@"Father instance address:%p",father);
    
    NSLog(@"Father instance isa:%@------%p",NSStringFromClass(fatherISA),fatherISA);
    NSLog(@"Father Class:%@------%p",NSStringFromClass(fatherClass),fatherClass);
    NSLog(@"%@",class_isMetaClass(fatherClass)?@"元类":@"非元类");
    
    NSLog(@"Father Class isa:%@------%p",NSStringFromClass(fatherClassISA),fatherClassISA);
    NSLog(@"Father Class Class:%@------%p",NSStringFromClass(fatherClassClass),fatherClassClass);
    NSLog(@"%@",class_isMetaClass(fatherClassClass)?@"元类":@"非元类");
    
    NSLog(@"Father Class Class isa:%@------%p",NSStringFromClass(fatherClassClassISA),fatherClassClassISA);
    NSLog(@"Father Class Class Class:%@------%p",NSStringFromClass(fatherClassClassClassClass),fatherClassClassClassClass);
    NSLog(@"%@",class_isMetaClass(fatherClassClassClassClass)?@"元类":@"非元类");
    
    NSLog(@"Father Class Class Class isa:%@------%p",NSStringFromClass(fatherClassClassClassISA),fatherClassClassClassISA);
    NSLog(@"Father Class Class Class Class:%@------%p",NSStringFromClass(fatherClassClassClassClass),fatherClassClassClassClass);
    NSLog(@"%@",class_isMetaClass(fatherClassClassClassClass)?@"元类":@"非元类");
    
    GrandFather *grandFather = [[GrandFather alloc] init];
    
    Class grandFatherISA = object_getClass(grandFather);
    Class grandFatherClass = [grandFatherISA class];
    
    Class grandFatherClassISA = object_getClass(grandFatherClass);
    Class grandFatherClassClass = [grandFatherClassISA class];
    
    Class grandFatherClassClassISA = object_getClass(grandFatherClassClass);
    Class grandFatherClassClassClass = [grandFatherClassClassISA class];
    
    Class grandFatherClassClassClassISA = object_getClass(grandFatherClassClassClass);
    Class grandFatherClassClassClassClass = [grandFatherClassClassClassISA class];
    NSLog(@"============GrandFather Info============");
    NSLog(@"GrandFather instance address:%p",grandFather);
    
    NSLog(@"GrandFather instance isa:%@------%p",NSStringFromClass(grandFatherISA),grandFatherISA);
    NSLog(@"GrandFather Class:%@------%p",NSStringFromClass(grandFatherClass),grandFatherClass);
    NSLog(@"%@",class_isMetaClass(grandFatherClass)?@"元类":@"非元类");
    
    NSLog(@"GrandFather Class isa:%@------%p",NSStringFromClass(grandFatherClassISA),grandFatherClassISA);
    NSLog(@"GrandFather Class Class:%@------%p",NSStringFromClass(grandFatherClassClass),grandFatherClassClass);
    NSLog(@"%@",class_isMetaClass(grandFatherClassClass)?@"元类":@"非元类");
    
    NSLog(@"GrandFather Class Class isa:%@------%p",NSStringFromClass(grandFatherClassClassISA),grandFatherClassClassISA);
    NSLog(@"GrandFather Class Class Class:%@------%p",NSStringFromClass(grandFatherClassClassClass),grandFatherClassClassClass);
    NSLog(@"%@",class_isMetaClass(grandFatherClassClassClass)?@"元类":@"非元类");
    
    NSLog(@"GrandFather Class Class Class isa:%@------%p",NSStringFromClass(grandFatherClassClassClassISA),grandFatherClassClassClassISA);
    NSLog(@"GrandFather Class Class Class Class:%@------%p",NSStringFromClass(grandFatherClassClassClassClass),grandFatherClassClassClassClass);
    NSLog(@"%@",class_isMetaClass(grandFatherClassClassClassClass)?@"元类":@"非元类");

在这里,我们分别创建了sonfathergrandFather三个对象,并且分别打印了对象的地址,对象的isa指向的Class的地址,类(类对象)的地址等,结果如下

============Son Info============
Son instance address:0x60c00002c980
Son instance isa:Son------0x104d614a0
Son Class:Son------0x104d614a0
非元类
Son Class isa:Son------0x104d61478
Son Class Class:Son------0x104d61478
元类
Son Class Class isa:NSObject------0x105d0de58
Son Class Class Class:NSObject------0x105d0de58
元类
Son Class Class Class isa:NSObject------0x105d0de58
Son Class Class Class Class:NSObject------0x105d0de58
元类
============Father Info============
Father instance address:0x60c000003e40
Father instance isa:Father------0x104d61450
Father Class:Father------0x104d61450
非元类
Father Class isa:Father------0x104d61428
Father Class Class:Father------0x104d61428
元类
Father Class Class isa:NSObject------0x105d0de58
Father Class Class Class:NSObject------0x105d0de58
元类
Father Class Class Class isa:NSObject------0x105d0de58
Father Class Class Class Class:NSObject------0x105d0de58
元类
============GrandFather Info============
GrandFather instance address:0x60c000003de0
GrandFather instance isa:GrandFather------0x104d61400
GrandFather Class:GrandFather------0x104d61400
非元类
GrandFather Class isa:GrandFather------0x104d613d8
GrandFather Class Class:GrandFather------0x104d613d8
元类
GrandFather Class Class isa:NSObject------0x105d0de58
GrandFather Class Class Class:NSObject------0x105d0de58
元类
GrandFather Class Class Class isa:NSObject------0x105d0de58
GrandFather Class Class Class Class:NSObject------0x105d0de58
元类

这个结果和我们上面的图基本就可以对应起来了:

对象的isa指向类(或者叫类对象)
类的isa指向元类
元类的isa指向根元类
根元类的isa指向自身

那么什么是元类呢?

通过上面的描述,我们知道,其实类自身也是一个对象,那么类对象为什么能够调用方法呢?这里我们就要提一下方法调用的流程了
通过对象的isa指针找到他的类
在类的method list中查找方法
如果没有找到该方法,继续前往父类中查找
直到查找到该方法,才去执行方法
所以,类对象调用方法的也会去通过它的isa查找它所属的类,也就是所谓的元类。
好,接下来我们来分析一下objc_class里面的各个成员

objc_class -> isa

这个isa用来指向其所属的类

objc_class -> super_class

super_class用来指向其父类

objc_class -> name

类的名称

objc_class -> version

类的版本

objc_class -> info

类的信息

objc_class -> instance_size

实例的大小

objc_class -> ivars

实例变量列表

objc_class -> methodLists

方法列表,我们看下MethodOC里的结构

typedef struct objc_method *Method;
struct objc_method {
    SEL method_name                                          OBJC2_UNAVAILABLE;
    char *method_types                                       OBJC2_UNAVAILABLE;
    IMP method_imp                                           OBJC2_UNAVAILABLE;
}

里面包含了SELmethod_typeIMP

objc_class -> cache

缓存列表

objc_class -> protocols

协议列表

你可能感兴趣的:(iOS Runtime(一)------类和对象的本质)