iOS Isa、Superclass、类、元 -- 对象的本质、内部原理

OC对象 主要分三种:

instance 对象(实例对象)

class 对象(类对象)

meta-class 对象 (元类对象)

1:一个实例对象 在内存中存储的信息:isa指针、其他变量(这个是成员变量的值,比如说,self.age = 10, 10放在里面)

2:类对象

  NSObject *objec1 = [[NSObject alloc] init];
        NSObject *objec2 = [[NSObject alloc] init];
        
        // 获取类对象的三种方式
        Class objectClass1 = [objec1 class];
        Class objectCalss2 = [objec2 class];
        Class objectClass3 = object_getClass(objec1);
        Class objectClass4 = object_getClass(objec2);
        Class objectClass5 = [NSObject class];
        

一个类的类对象是唯一的,在内存中是一份的,所以上述objectClass1、2、3、4、5地址是一样的

2018-07-04 20:39:35.659080+0800 new[4539:831047] 0x7fffb08b9140,0x7fffb08b9140,0x7fffb08b9140,0x7fffb08b9140,0x7fffb08b9140

类对象在内存中存储的信息:isa指针、superclass指针、类的属性信息(@property)、类的对象方法信息(instance method)(减号的方法)、类的协议信息(protocol)、类的成员变量信息(ivar)(这个成员变量是 成员变量的名字、还有成员变量的类型,比方说 string类型,名字叫age)

iOS Isa、Superclass、类、元 -- 对象的本质、内部原理_第1张图片

3:meta-class 元类对象

获取元类对象

跟class和实例对象不是一种地址

iOS Isa、Superclass、类、元 -- 对象的本质、内部原理_第2张图片

 

class方法返回的就是类对象,不管你调用多少次,[[NSObject class] class]

元类对象在内存中储存的信息:类方法。

objectMetaClass是NSObject的meta-Class对象

每个类在内存中有且只有一个metal-Class对象

meta-Class对象和class对象的内存结构是一样的,但是用途不一样,在内存中存储的信息主要包括:isa指针、superclass、类方法信息。

可以判断是否是元类对象。:

class_isMetaClass(objectMetaClass);

 

 

 

object_getClass与objc_getClass分别是什么意思

 

 

 

A>: Class objc_getClass(const char *name)

a:传入的是字符串类名,返回对应的类对象。

 

 

B>: Class object_getClass(id obj)

a:传进去的obj可能是instance对象、class对象、meta-class对象

b:如果是instance对象,返回class对象

c:如果是class对象,返回的是meta-class对象

d:如果是meta-class对象,返回的是NSObject(基类)的meta-class对象。

 

C>: -(Class)class 、+(Class)class

返回的就是类对象

iOS Isa、Superclass、类、元 -- 对象的本质、内部原理_第3张图片

 

isa指针:

iOS Isa、Superclass、类、元 -- 对象的本质、内部原理_第4张图片

class对象的superclass指针:Student继承自Person,Person继承自NSObject。当Student实例变量去调用实例方法时的过程。

@interface Person : NSObject
{
    int _df;
}

- (void)personMethod;

@end

@implementation Person

- (void)personMethod
{   
}
@end

@interface Student : Person
{
    double _no;
}

- (void)studentMethod;

@end

@implementation Student

- (void)studentMethod
{   
}
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        Student *stu = [[Student alloc] init];
        [stu personMethod];   
    }
    return NSApplicationMain(argc, argv);
}

这个原理过程就是下面图中所示,stu先按照上图所示的,stu的实例对象的isa指针,找到本身stu类(因为类里有对象方法,同时有superclass指针,)发现并未有该方法,根据superclass指针,找到Person的类对象,就能够找到Person类的对象方法,正好有刚调用的personMehod方法,即可实现。

iOS Isa、Superclass、类、元 -- 对象的本质、内部原理_第5张图片

假设Student类对象调用 load方法,那么过程就是下面图中所示:Student类根据isa指针找到自己的meta-class对象,在元类对象中并未发现load方法,就会根据superclass找到父类的meta-class对象,也就是Person的元类对象,发现也没有,再根据person原类对象的superclass找到父类也就是NSObject的meta-class对象,从而找到load方法。这里需要注意,假设NSObject没有load方法,那么现在NSObject这个基类的meta-class的superclass会找到NSObject的class,如果再没找到,才会报错。

iOS Isa、Superclass、类、元 -- 对象的本质、内部原理_第6张图片

总结一下:就是superclass找的是类方法 都是找的meta-class对象  如果找的是实例方法 ,那么找的都是类对象。

每一个类 都有自己的元类对象

iOS Isa、Superclass、类、元 -- 对象的本质、内部原理_第7张图片

iOS Isa、Superclass、类、元 -- 对象的本质、内部原理_第8张图片

假设Person和Student都有实例test方法。【student test】调用的时候,会直接调用student的test方法。原因:面向对象的思想的话是子类重写父类,那么肯定会调用子类的方法。如果按照上面的本质去解释的话:子类isa指针找到本类class对象,发现有test方法,那么它就直接执行了,不会再找父类了。

 

如果是

 

验证问题:

这个是NSObject分类,只实现了实例方法test。
#import "NSObject+test.h"

@implementation NSObject (test)

- (void)test
{
    NSLog(@"sfd");
}



@end
这里是person方法,并未实现test类方法
@interface Person : NSObject

+ (void)test;

@end

@implementation Person

@end
 
 
#import "NSObject+test.h"
int main(int argc, const char * argv[]) { @autoreleasepool { 
[Person test];
 }
 return NSApplicationMain(argc, argv);
}

 

 

那么这个能够调用? 是否会报错? 答案很明显,不会

 

 

2018-07-10 20:08:51.314998+0800 new[1765:218776] sfd

原因就是上面基类的meta-class方法如果没有找到对应的类方法的时候,它的superclass指针会指向基类的class对象,也就是NSObject类,找到了test方法,所以就调用了。对于本质objc_Send()方法而言,是没有减号和加号的区别方法的,所以直接调用。
 

注意:

isa不是直接指向本类的对象的,从64bit开始,需要一次运算才能计算出真实的地址

iOS Isa、Superclass、类、元 -- 对象的本质、内部原理_第9张图片

iOS Isa、Superclass、类、元 -- 对象的本质、内部原理_第10张图片

iOS Isa、Superclass、类、元 -- 对象的本质、内部原理_第11张图片

但是superclass是直接指向的,并不需要转换

iOS Isa、Superclass、类、元 -- 对象的本质、内部原理_第12张图片

 

2:对象的isa指针指向哪里?

instance对象isa指向class对象

class对象isa指向meta-class对象

meta-class对象isa指向基类meta-class对象

 

3:OC的类信息存放在哪里?

对象方法、属性、成员变量、协议信息存放在class对象中

类方法存在meta-class对象中

成员变量的具体值,存放在instance对象

 

 

 

 

 

 

你可能感兴趣的:(oc)