本系列文章我们一起探讨Objective-C对象模型(Object Model),本文主要讨论与Object Model相关的底层数据结构。
©原创文章,转载请注明出处!
什么是对象模型(Object Model)
说起Object Model不得不提起Stanley B. Lippman以及他的著作《Inside the C++ Object Model》。Lippman作为C++大师,参与设计了第一套C++编译程序cfront,其主要著作相信大家也耳熟能详:《C++ Primer》,《Inside the C++ object model》,《Essential C++》等。
在《Inside the C++ Object Model》中认为Object Model主要阐述两个层次的问题:
在语言层面对Object-Oriented Programming的支持(广大程序猿天天要用到的各种高大上的OOP特性)
Object-Oriented Programming的底层实现机制(伟大的编译器如何处理这些高大上的OOP特性)
嗯,本文主要讨论第二个问题。
Objective-C中与Object Model相关的数据类型
NSObject——万物之源
1 | @interface NSObject <NSObject> |
我们都知道正常情况下所有的Objective-C类都是继承自NSObject
这个原始基类,isa
这个Objective-C Object的精神领袖就包含在其中。
继续…
objc_class——类的元数据
1 | typedef struct objc_class *Class; |
Class就是一个指向objc_class struct
的指针。
1 | struct objc_class objc_class public |
在Objective-C runtime的公开接口中可以看到objc_class
是一个指向自身类型的结构体(从Objective-C 2.0开始,该结构体中其余成员已不再可用)。
由于Objective-C runtime已经开源,我们可以进一步一探究竟。
在最新的开源代码objc4-551.1中(以下代码只摘取了其中的成员变量):
1 | struct objc_class : objc_object |
可以看到objc_class
继承自objc_object
,这也间接说明了Objective-C中一个重要的概念:类也是对象。
objc_object
1 | struct objc_object |
在objc_object
看到了久违的isa
指针。
额…,此时或许有个疑问了,类的成员变量、方法等元信息咋还没登场?
不要急,他们来了…
class_rw_t
或许已经注意到在objc_class
结构中有个成员变量uintptr_t data_NEVER_USE;
。
没错,它就是指向class_rw_t
结构体的指针(其中做了一些优化,在此不作过多讨论,只简单的认为data_NEVER_USE
指向class_rw_t
结构体)。
1 | struct class_rw_t |
其中,类名name
、实例大小instanceSize
、子实例相对整个实例的偏移instanceStart
以及实例变量ivars
等信息保存在class_ro_t
中,方法列表method_lists
、协议protocols
保存在class_rw_t
中。
这里有个小细节,当类只有一个方法时,该方法直接保存在method_list
中,否则保存在方法列表中method_lists
。
1 | if (newCount > 1) |
我们都知道可以在分类中添加方法,而不能添加成员变量(或属性),从其内部实现我们也能得出这样的结论:
方法是保存在方法表里面的(只有一个方法情况除外),因此添加方法不会改变实例的大小,也不会引起实例内存布局的改变;
若添加成员变量将引起实例内存布局的改变(
class_ro_t
的instanceStart
、instanceSize
),同时在class_rw_t
中class_ro_t
被声明为const
,因此想改也改不了。
Other
1 | struct method_list_t |
我们可以看到Objective-C的Object-Orient是构建在C语言结构体基础之上,大到类、对象,小到成员变量、方法等等。
插个题外话:个人感觉C语言是一门简洁、优雅的语言,而这一切都归功于指针,可以说指针是C语言的灵魂。