美文网首页
OC中的对象、类与元类的关系

OC中的对象、类与元类的关系

作者: 大成小栈 | 来源:发表于2021-06-22 15:24 被阅读0次

先以运行时动态创建一个class为引,通过剖析创建的class pair来弄明白到底meta-class是什么以及更深入的了解它对于OC中对象、类的意义。

1. 在运行时创建一个类

在运行时创建一个NSError的子类:

Class newClass = objc_allocateClassPair([NSError class], "RuntimeErrorSubclass", 0);
class_addMethod(newClass, @selector(report), (IMP)ReportFunction, "v@:");
objc_registerClassPair(newClass);

添加一个实例方法ReportFunction给该类,具体实现如下:

void ReportFunction(id self, SEL _cmd) {    
  
  NSLog(@"This object is %p.",self);    
  NSLog(@"Class is %@, and super is %@.",[self class],[self superclass]);     
  Class currentClass = [self class];    
  for( int i = 1; i < 5; ++i )    {        
    NSLog(@"Following the isa pointer %d times gives %p",i,currentClass);          
    currentClass = object_getClass(currentClass);    
  }    
  NSLog(@"NSObject's class is %p", [NSObject class]);    
  NSLog(@"NSObject's meta class is %p",object_getClass([NSObject class]));
}

在运行时创建一个类需要三步:
1.使用objc_allocateClassPair为"class pair"分配空间;
2.使用class_addMethod为类添加方法和成员;
3.使用objc_registerClassPair注册你创建的这个类,使其可用。

可见objc_allocateClassPair只返回一个值:Class。"class pair"即< class, meta-class>这个成对出现的结构关系,对于"class pair"的另一半就是指meta-class

2. 一个数据结构何以称为对象

每个对象都会有一个它所属的类,这是面向对象的基本概念。在OC中,这对所有数据结构有效,只要在数据结构恰当的位置有一个指针指向一个class,那么,它都可以被认为是一个对象。在OC中,一个对象所属于哪个类,是由它的isa指针指向的。这个isa指针指向这个对象所属的class。

实际上,OC中对象的定义是如下的样子:

typedef struct objc_object {      
  Class isa;
}*id;

即,任何以一个指向Class的指针作为首个成员的数据结构都可以被认为是一个objc_object。

最重要的特性就是,你可以向OC中的任何对象发送消息,如下这样:

[@”stringValue" writeToFile:@"/file.txt atomically:YES encoding: NSUTF8StringEncoding error:NULL];

运行原理就是,当你向一个OC对象发送消息时(此处为@"stringValue"),运行时系统会根据对象的isa指针找到这个对象所属的类,这个类会包含一个所有实例方法的列表及一个指向superclass的指针以便可以找到父类的实例方法。运行时库会在类的方法列表以及向上父类的方法列表中寻找符合这个selector(此处selector为"writeToFile:atomically:encoding:error")的方法。找到后即运行这个方法。

3. meta-class 的本质

由上述可知一个OC的类也是一个对象,意思就是你可以向一个类发送消息。

NSStringEncoding defaultStringEncoding = [NSString defaultStringEncoding];

其中,defaultStringEncoding 被发送给了NSString类,也就是说Class的数据结构也是以isa指针开始的,在二进制级别上与objc_object是完全兼容的。然后一个类结构的下一个字段一定是一个指向super class的指针(或者指向nil,对于基类而言)。
一个类的结构是如何被定义的,有很多方法,依赖于你的运行时库版本,但是不管哪种方法,他们都是以一个isa作为第一个字段,接着是superclass字段。

typedef struct objc_class *Class;struct objc_class{     
  Class isa;     
  Class super_class;  // followed by runtime specific details...
};

为了可以调用类方法,这个类的isa指针必须指向一个包含这些类方法的类结构体。这样就引出了meta-class的概念:meta-class是一个类对象的类。
1.当你向一个对象发送消息时,runtime会在这个对象所属的那个类的方法列表中查找。
2.当你向一个类发送消息时,runtime会在这个类的meta-class的方法列表中查找。
meta-class之所以重要,是因为它存储着一个类的所有类方法。每个类都会有一个单独的meta-class,因为每个类的类方法基本不可能完全相同。

4. meta-class的类

meta-class,就像Class一样,也是一个对象。你依旧可以向它发送消息调用函数,meta-class也会有一个isa指针指向其所属类。所有类的meta-class使用相应基类的meta-class作为他们的所属类。具体而言,任何NSObject继承体系下的meta-class都使用NSObject的meta-class作为自己所属的类。
根据这个规则,所有的meta-class使用基类的meta-class作为它们的类,而基类的meta-class也是属于它自己,也就是说基类的meta-class的isa指针指向它自己。(译:完美的闭环)

就像一个类使用super_class指针指向自己的父类一样,meta-class的super_class会指向类的super_class的meta-class。一直追溯到基类的meta-class,它的super_class会指向基类自身。(译:万物归根)

这样一来,整个继承体系中的实例、类和meta-class都派生自继承体系中的基类。对于NSObject继承体系来说,NSObject的实例方法对体系中所有的实例、类和meta-class都是有效的;NSObject的类方法对于体系中所有的类和meta-class都是有效的。

实例、类与元类的关系

执行例中ErportFunction方法可以证实以上论述:

id instanceOfNewClass = [[newClass alloc]initWithDomain:@"some Domain" code:0 userInfo:nil];
[instanceOfNewClass performSelector:@"report)];
[instanceOfNewClass release];

以下是程序的输出:

This object is 0x10010c810.
Class is RuntimeErrorSubclass, and super is NSError.
Followingthe isa pointer 1times gives 0x10010c600
Followingthe isa pointer 2times gives 0x10010c630
Followingthe isa pointer 3times gives 0x7fff71038480
Followingthe isa pointer 4times gives 0x7fff71038480
NSObject's class is 0x7fff710384a8
NSObject's meta class is 0x7fff71038480

这些地址的值并不重要,重要的是它们说明了从实例、class到meta-class到NSObject的meta-class的整个流程。

总结:
1.meta-class是类对象的类,每个类都有自己单独的meta-class;
2.对于所有NSObject继承体系下的类,NSObject的实例方法和协议方法对他们和他们meta-class的对象都要有效。
3.所有的meta-class使用基类的meta-class作为自己的基类,对于顶层基类的meta-class也是一样,只是它指向自己而已。

参考链接:
https://www.cocoawithlove.com/2010/01/what-is-meta-class-in-objective-c.html

iOS探寻+(void)load方法的执行时机
https://www.jianshu.com/p/4b93b40977b5

相关文章

  • iOS Runtime笔记

    相信大家对上图应该不陌生,图中说明了OC中对象的本质以及对象、类与元类的关系,这个也是OC的基础,属于runtim...

  • OC中的对象、类与元类的关系

    先以运行时动态创建一个class为引,通过剖析创建的class pair来弄明白到底meta-class是什么以及...

  • iOS runtime

    文章目录 OC中类和对象的本质 实例对象,类,元类的关系 类的属性 类的方法 消息发送机制 Runtime api...

  • Objective-C基础学习之类与对象

    这章主要记录一下OC中类与对象的关系,在一个类中怎么设计使用的对象! 1.类与对象的关系 面向对象的核心就是对象,...

  • oc对象实现图解

    ios第一篇(oc对象) ios类对象和元类对象以及对象的关系 类对象中存储的是对象的实例方法,属性,成员变量,协...

  • iOS-对象、isa指针、SuperClass

    OC中对象分类 分为三类:实例对象、类对象、元类对象 instance对象(实例对象) class对象(类对象) ...

  • Runtime:OC对象、类、元类的本质

    零、Runtime是什么一、OC对象的本质二、OC类的本质三、OC元类的本质四、Runtime关于对象、类、元类的...

  • 1.5. 类与对象

    目录 类与对象的关系 1.类与对象的关系 面向对象的核心就是对象,那怎么创建对象?OC中创建对象比较复杂, 首先要...

  • NSObject底层实现

    NSObject的实现(OC2.0) 对于实例对象、类对象、元类对象 isa和superclass的关系还得看这张...

  • Object-C 方法查找原理(对象、isa和SuperClas

    Q:OC中对象分类 A:总共为三类:实例对象、类对象、元类对象 instance对象(实例对象) class对象(...

网友评论

      本文标题:OC中的对象、类与元类的关系

      本文链接:https://www.haomeiwen.com/subject/mvtmyltx.html