深入理解Objective-C中实例、类对象、元类对象之间的关系

栏目: Objective-C · 发布时间: 4年前

内容简介:实例、类对象、元类对象之间的关系可以用下面这张经典的图来展示:总结:我们知道如果调用类方法,会沿着元类对象的继承链依次向上查找方法的实现。

实例、类对象、元类对象之间的关系可以用下面这张经典的图来展示:

深入理解Objective-C中实例、类对象、元类对象之间的关系

总结:

  • 实例的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的类名。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

遗传算法

遗传算法

王小平 / 西安交通大学出版社 / 2002-1 / 40.00元

《遗传算法:理论应用与软件实现》全面系统地介绍了遗传算法的基本理论,重点介绍了遗传算法的经典应用和国内外的新发展。全书共分11章。第1章概述了遗传算法的产生与发展、基本思想、基本操作以及应用情况;第2章介绍了基本遗传算法;第3章论述了遗传算法的数学基础;第4章分析了遗传算法的多种改进方法;第5章初步介绍了进化计算理论体系;第6章介绍了遗传算法应用于数值优化问题;第7章介绍了遗传算法应用于组合优化问......一起来看看 《遗传算法》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

MD5 加密
MD5 加密

MD5 加密工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试