首页 > 代码库 > Objective-C 对象模式深入分析
Objective-C 对象模式深入分析
The Objective-C object model
作为一名Objective-C的软件开发者,你可以在不需要理解Objective-C的鼻祖C语言和Objective-C所采用的对象模型的情况下,依然能够完成许多的工作。事实上,因为这些特性的确很复杂,要去学习这些个对象模型可能会令你感到望而却步。
虽然这个问题的确比较复杂,但是还是有努力去学习它的必要性的,因为你最终还是会需要和Objective-C运行时的情况打交道的,而那个时候理解了对象模型将会帮助你更好地解决此类问题。
端起一杯茶,或者一杯咖啡,跟着我一起来探索Objective-C的对象模型吧。
对象是类的实例
看起来这个是很明显的,但是我们不妨花些时间来认真思考一下当我们说“一个对象是一个类的实例”的时候,这句话意味着意味着什么。以下面的代码举例说明。
NSString *name = [NSString stringWithFormat:@"%@", @"Peter"];这个代码看起来更像是人造的,而不是实际使用需要的一段代码,但是它对于展示Objective-C运行时的具体工作方式是很重要的。当上述代码执行完毕后,我们最终获取到的是一个叫做name的变量,该变量是NSString类的一个实例,请细想一下以下知识:
- 对象(类的实例)是用来保存状态的
- 一个对象的状态保存在它的实例变量内。比如,上述代码中的name变量分配了一些内存用来保存字符串内容"Peter"
- name变量同时也包含了一个指向它所在的类(NSString)的指针
- Objective-C里面,对象不包含任何方法(行为),仅仅保存着状态信息
- 类只包含方法,不包含任何状态信息。这些包含的方法是他们的实例能够响应的方法(即实例方法)
- 为了使得我们清楚一些,我们再重复一遍:对象包含了保存的状态(即实例变量),而类包含了保存的行为(方法)
实例方法图
上图中蓝色的框框表示name变量(类NSString的一个实例)。根据上图所示,让我们来看一下,如果你向变量name发送length的消息,那么会发生什么?
NSUInteger len = [name length];
- 首先Objective-C会询问变量name是哪个类的实例,因为所有的方法都包含在类里面,所以从那里面才能开始寻找方法length在哪。
- 因为name是类NSString的实例变量,所以Objective-C将会先找到类NSString,然后开始查找方法length。
- 如果Objective-C在类NSString里面找到了方法length,那么它就会停止查找并开始执行方法。否则,它就会根据类的继承关系继续查找。
需要说明一点的是,上面所描述的过程是经过我的简化的,我没有考虑方法存储的其他情况。(比如Objective-C的分类)
类也是对象
既然类能够保存它的实例的方法(实例方法),那么类方法保存在哪里呢?我们再来看看创建变量name的代码:
NSString *name = [NSString stringWithFormat:@"%@", @"Peter"];上述代码中,消息stringWithFormat:是向类NSString发送的。类可以接收消息吗?如果可以,那么那些方法保存在哪里呢?事实上是这样的,Objective-C的语法隐藏了一些东西,他隐藏了类也是对象的事实。
如果类NSString是一个对象,那就意味着它一定是从一个保存着它的方法的类实例化来的。这个猜测是对的,不过在深入这个问题之前,我们再来看一段代码:
@interface Person : NSObject {} + (void) aClassMethod; - (void) anInstanceMethod; @end也许你看过这种类似的代码很多很多,但是这这段代码干嘛的?
- 声明了一个类,该类是Person
- 这个类用来保存实例方法
- 在这段代码的背后也创建了另外的一个类,不幸的是这个额外的类名也是Person,只不过它是Person元类而已
- Person元类会保存着Person的类方法
看起来现在的问题越来越复杂了,因为相同的名字用了一遍又一遍,回到最初的变量name上来讨论,我们可以说:
- 变量name是类NSString的一个实例
- 类NSString是一个NSString元类实例化的一个对象
- 如果你向对象name发送消息length,那么Objective-C会去类NSString查找这个方法
- 如果你向对象NSString发送stringWithFormate:消息,Objective-C会在NSString元类里面查找这个方法
- NSString是一个类,也是一个对象,类也是一个对象
这里是另外一个类图示意图
元类方法(类方法)图
这一次,蓝色的框框表示的是NSString对象,我们再来看看创建name对象的代码:
NSString *name = [NSString stringWithFormat:@"%@", @"Peter"];当向对象NSString发送消息stringWithFormate:的时候,Objective-C将会:
- 询问NSString对象是哪个类的一个实例,哪一个是它的元类
- 开始在NSString的元类里面查找方法stringWithFormate:,如果没找到,它会继续根据类的类的继承关系继续查找
当然,因为NSString继承自NSObject,所以NSString元类继承自NSObject元类。
奇怪的NSObject继承
如果到了这里你还算清醒的话,那么利用你现在所掌握的关于Objective-C对象模型的知识够你去了解你的代码在运行时会发生了什么。可能还有一个问题你想知道:为了么NSObject元类好像继承自NSObject类?这是因为本来就是这样子的。
考虑一下以下情况:
- NSObject为它的实例保存着方法(保存实例方法)
- NSObject元类为类NSObject保存着方法。(保存类方法)
- NSObject元类继承自非元类NSObject
- 因此,NSObject的实例方法也是类方法,这些方法在所有Objective-C的元类方法的查找路径中
有点奇怪,但是如果你再去看看上面的图,你就应该会更清楚些了。
Objective-C 对象模式深入分析
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。