深入理解Objective-C中实例、类对象、元类对象之间的关系
栏目: Objective-C · 发布时间: 5年前
内容简介:实例、类对象、元类对象之间的关系可以用下面这张经典的图来展示:总结:我们知道如果调用类方法,会沿着元类对象的继承链依次向上查找方法的实现。
实例、类对象、元类对象之间的关系可以用下面这张经典的图来展示:
总结:
- 实例的isa指向类对象
- 类对象的isa指向元类对象
- 元类对象的isa指针指向根元类对象
- 根元类的父类是根类对象
根元类的父类是根类对象意味着什么呢?
我们知道如果调用类方法,会沿着元类对象的继承链依次向上查找方法的实现。
因为跟元类的父类是根类对象,所以如果在跟元类中无法查找到该方法的实现,会到根类对象中去查找。
而根类对象中的方法都是实例方法。
所以这意味着,如果一个类的类方法没有被实现,就会去调用它的根类(NSObject)中的同名实例方法。
我们用代码验证一下。
为 NSObject
新建一个 Category
,并添加一个名为 foo
的实例方法。方法的实现只是简单打印 foo
字符串
//NSObject+Foo.h #import <Foundation/Foundation.h> @interface NSObject (Foo) - (void)foo; @end //NSObject+Foo.m #import "NSObject+Foo.h" @implementation NSObject (Foo) - (void)foo { NSLog(@"foo foo"); } @end 复制代码
新建一个 UIView
的子类,并在这个子类的.h文件中声明一个名为 foo
的 类方法 ,但在.m文件中并不实现它。
// CView.h #import <UIKit/UIKit.h> @interface CView : UIView + (void)foo; @end // CView.m #import "CView.h" @implementation CView @end 复制代码
然后调用这个类方法 [CView foo];
按理说我们没有实现 + (void)foo;
程序应该崩溃。但是,实际上会调用NSObject的Category中的实例方法 - (void)foo
,打印出"foo foo",非常神奇
使用super关键字调用方法的时候,发生了什么
如果上面提到的CView有这样一个初始化方法:
#import "CView.h" @implementation CView - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { NSLog(@"%@",NSStringFromClass([self class])); NSLog(@"%@",NSStringFromClass([super class])); } return self; } @end 复制代码
问:如果调用这个初始化方法,打印的结果是什么?
要解答这个问题,我们需要了解消息传递的过程?
我们知道,在OC中方法调用 [obj method]
会被编译器编译为 objc_msgSend
,它的定义为 objc_msgSend(id _Nullable self, SEL _Nonnull op, ...)
前两个参数是固定的,分别是消息的接受者和方法选择器。
那么super关键字调用方法会被转换为 objc_msgSendSuper(struct objc_super * _Nonnull super, SEL _Nonnull op, ...)
,第一个参数为 objc_super
指针
objc_super是下面的数据结构:
/// Specifies the superclass of an instance. struct objc_super { /// Specifies an instance of a class. __unsafe_unretained _Nonnull id receiver; /// Specifies the particular superclass of the instance to message. #if !defined(__cplusplus) && !__OBJC2__ /* For compatibility with old objc-runtime.h header */ __unsafe_unretained _Nonnull Class class; #else __unsafe_unretained _Nonnull Class super_class; #endif /* super_class is the first class to search */ } 复制代码
其中的 receiver
是类的一个实例,也就是self。
也就是说,最终消息的接受者还是self这个实例。只不过, objc_msgSendSuper
查找方法实现的过程,是从self的父类对象开始的。
但是class方法是在根类 NSObject
中定义的,所以不论是 [self class]
还是 [super class]
都会调用NSObject中的实现,而且消息的接收者也是一样的,都是self这个实例。所以打印结构也是一样的,都打印self的类名。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- OC对象的本质 实例对象,类对象,元类对象
- 面向对象-什么是类、实例化、对象、抽象类
- PHP 实例化对象注销
- iOS-对象实例化alloc方法
- Stinger--实践实现特定实例对象的AOP
- [ PHP 内核与扩展开发系列] 类与面向对象:访问对象实例的属性和方法
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。