Runtime的初步认识——结构体与类
2016-05-08 12:33
197 查看
Runtime的初步认识
Runtime的初步认识Runtime介绍
类与结构体的关系
结构体解析
结构体的作用
纠正
Runtime介绍
学习一个东西至少要先知道它是个啥,你一定听说过“运行时是 Objective-C 的一个特色”,这里的“运行时”就是指 runtime 了。runtime是在自 iOS 平台开放并基于 Objective-C 语言开发后的一个编程语言上的高级技术。
学习runtime的目的并不是为了开发,而是让你更好的理解 Objective-C 的工作原理,从而熟练的运用 Objective-C 来开发应用。当然,你也可以利用 runtime 的理论在面试的时候给自己加分。
Runtime 很强大,很强大,很强大,强大的让你无言以对。甚至因为 Runtime,让 Objective-C 与别的面向对象的语言有着极大的不同。
曾经在论坛上看到这样的一段话“如果这世界上没有 OC ,一个会熟练使用 Runtime 的人就可以写出一个 OC。”其实苹果就是利用runtime制造了现在的Objective-C 语言。runtime只是给C语言插上了面向对象的翅膀,然后他就可以上天与各路面向对象语言一起飞了︿( ̄︶ ̄)︿。
类与结构体的关系
任何一个可执行的编程语言,最终编译后都会变成汇编,然而 OC 到汇编并不是一步的,其中还经历了 C,甚至还有可能是 C++。但是 C 语言是最接近汇编语言的,因为 C 语言有直接的内存操作。而 C 语言又是用英语写,人易看懂的语言。OC 在变成汇编前,它先变成了 C,然后才是汇编。
OC 是一个面向对象的语言,C 语言是面向过程的。OC 和 C 最大的区别就是 C 没有 “类”。那么,OC 变成 C 语言后,面向对象特有的类变成了什么,类是怎么存在面向过程语言中的? 到这个问题的时候,runtime的作用就展现出来了。
Runtime用面向过程语言(C) 中的结构体(struct) 做出了类(class) 在面向对象语言(OC) 中的实现。其实我们可以看见这个Class在C中变成结构体之后是什么样子的。
我们可以在文件中导入头文件
#import <objc/runtime.h>
然后利用
command键和
鼠标左键进入 runtime 的头文件定义,你会发现一个如下的结构体
struct objc_class { Class isa OBJC_ISA_AVAILABILITY; #if !__OBJC2__ Class super_class OBJC2_UNAVAILABLE; const char *name OBJC2_UNAVAILABLE; long version OBJC2_UNAVAILABLE; long info OBJC2_UNAVAILABLE; long instance_size OBJC2_UNAVAILABLE; struct objc_ivar_list *ivars OBJC2_UNAVAILABLE; struct objc_method_list **methodLists OBJC2_UNAVAILABLE; struct objc_cache *cache OBJC2_UNAVAILABLE; struct objc_protocol_list *protocols OBJC2_UNAVAILABLE; #endif } OBJC2_UNAVAILABLE;
这个结构体的名字叫
objc_class,其实他就是我们平时在OC中常用的
Class。到这里我们又会疑问它们俩是怎么发生关系的呢。
继续导入头文件
#import <objc/objc.h>
点进去就会看到这几行
/// An opaque type that represents an Objective-C class. typedef struct objc_class *Class; /// Represents an instance of a class. struct objc_object { Class isa OBJC_ISA_AVAILABILITY; }; /// A pointer to an instance of a class. typedef struct objc_object *id;
如果你有 C 语言基础,你一定知道
typedef的语法以及含义
苹果重新定义
objc_class这个结构体,并取名为
*Class,也就是说
Class是一个
objc_class的一个指针。同样
id也是
objc_object的一个指针。
非常的显然了,平时我们这样编写代码:
id obj = [[NSObject alloc] init];
obj是一个
NSObject的一个对象,而本质上
obj是一个
id,而
id又是一个
objc_object结构体的一个指针,所以你其实得到的只是一个结构体的指针而已。
那么同样,类其实也是有对象的,因为你可以这样打:
Class c = [obj class];
这样 c 就是 objc 的类型了,然后你可以直接通过这个 c 来创建对象:
id other_obj = [[c alloc] init];
如果你细心的话,你会发现
Class保存的一个类对象,但本质是
objc_class的指针
id保存一个对象,但本质是
objc_object的指针
而我们所做的所有面向对象编程,对对象的操作,最终都会落实到这些结构体上。这些结构体保存着一个对象的所有信息。
结构体解析
objc/objc.h和
objc/runtime.h两个头文件的内容,让大家好看一些:
typedef struct objc_class { Class isa OBJC_ISA_AVAILABILITY; #if !__OBJC2__ Class super_class OBJC2_UNAVAILABLE; const char *name OBJC2_UNAVAILABLE; long version OBJC2_UNAVAILABLE; long info OBJC2_UNAVAILABLE; long instance_size OBJC2_UNAVAILABLE; struct objc_ivar_list *ivars OBJC2_UNAVAILABLE; struct objc_method_list **methodLists OBJC2_UNAVAILABLE; struct objc_cache *cache OBJC2_UNAVAILABLE; struct objc_protocol_list *protocols OBJC2_UNAVAILABLE; #endif } *Class OBJC2_UNAVAILABLE; //以上是一个类的结构体 typedef struct objc_object { Class isa OBJC_ISA_AVAILABILITY; } *id ; //以上是一个对象的结构体
我们从对象结构体开始介绍(objc_object)。
当我们获取到一个对象的时候,说白了就是一个对象的引用,也就是一个
id。上面那个结构体被重定义为
*id,那么
id就是一个
objc_object的指针。
这个结构体里有一个成员,是类型为
Class的一个
isa。我们可以这么理解,我们实例化出来的对象,它实际上只保存一个
类的结构体的指针,也就为了说明这个对象是由什么类实例化出来的。
现在来看看类的结构体(objc_class)。
对象被实例化出来后,他就保存了那个创造自己的类的信息,这个信息也就是一个
objc_class结构体,那么我们来看看,这个结构体到底保存了那些关于一个类的信息
Class isa
保存一个
objc_class的一个指针,叫做
isa
这个
isa和
objc_object中的重名,具体内容和区别之后分析
Class super_class
保存一个
objc_class的一个指针,叫做
super_class
显而易见,这里就是一个指向父类的指针,为了保存自己是从哪里集成来的
char *name
保存这个类名的字符串指针
这个也不用多解释,NSObject类里这里的值就是”NSObject”
long version
long info
long instance_size
以上三个成员不多解释,用不到
struct objc_ivar_list *ivars
从定义可以看出,是一个结构体指针,保存着这个类的实例变量列表
struct objc_method_list **methodLists
从定义可以看出,是一个结构体指针,保存着这个类的方法列表
struct objc_cache *cache
从定义可以看出,是一个结构体指针,保存缓存
什么东西可以保存到缓存,这个下文会解释
struct objc_protocol_list *protocols
从定义可以看出,是一个结构体指针,保存协议列表
我们写的类,实际上也就是这些东西,一些实例变量、一些方法、实现一些协议,还给类取了个名字,拥有父类的所有特性。
现在我们终于知道我们写的类最终会变成了一个什么样的结构体。
结构体的作用
结构体,就是一块内存,用于统一保存大小不同且不变的集合。在 C 语言中,允许我们去创建与修改结构体,也就是动态的去修改OC中的类。
我们可以动态的修改这些结构体内的内容,甚至你在一个对象创建后,你可以真真切切地修改他的类型和父类。你甚至可以为一个类动态的增加方法,而不是在 .m 文件中去写方法。同样,你甚至可以去修改苹果写的类。这也是runtime如此强大的地方。先介绍到这里。近期会再更新篇关于runtime应用的文章。
可以继续看看
《Runtime的初步认识——消息机制》
《Runtime的实践——给一个类添加属性(关联对象)》
《Runtime的实践——方法交换》
纠正
我们在<objc/runtime.h>头文件中看到的结构体是老版本的
objc_class结构,新版本的大家可以去下载最新
runtime源码http://opensource.apple.com//tarballs/objc4/ 。
相关文章推荐
- Python学习笔记:元组(tuple)有关内容
- 第六次
- 2016-5
- DataSet用法详细
- EPI (Heap) Merge Multiple sorted arrays.
- MySQL 服务无法启动 ERROR 2003 (HY000): Can't connect to MySQL server on 'localhost' (10061)
- DIY3.5mm耳机头手机红外遥控器
- 机器学习笔记06:神经网络的表示(Neural Networks-Representation)
- C# 托管资源和非托管资源
- Oracle 12c Windows安装、介绍及简单使用(图文)
- 单元测试——Qunit
- Python 递归
- ApplicationId 与 PackageName
- 《java入门第一季》之面向对象(修饰符的概念和总结)
- 《java入门第一季》之面向对象(修饰符的概念和总结)
- 百度面试总结
- 20145221 《Java程序设计》实验报告五:网络编程及安全
- 20145210实验五《Java网络编程》
- word:Can't find the word document templant:WordToRqm.doc
- Linux下C结构体初始化