深入理解Objective-C中实例、类对象、元类对象之间的关系
栏目: Objective-C · 发布时间: 6年前
内容简介:实例、类对象、元类对象之间的关系可以用下面这张经典的图来展示:总结:我们知道如果调用类方法,会沿着元类对象的继承链依次向上查找方法的实现。
实例、类对象、元类对象之间的关系可以用下面这张经典的图来展示:
总结:
- 实例的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 内核与扩展开发系列] 类与面向对象:访问对象实例的属性和方法
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Domain-Driven Design
Eric Evans / Addison-Wesley Professional / 2003-8-30 / USD 74.99
"Eric Evans has written a fantastic book on how you can make the design of your software match your mental model of the problem domain you are addressing. "His book is very compatible with XP. It is n......一起来看看 《Domain-Driven Design》 这本书的介绍吧!