#include <stddef.h>
typedef const struct objc_selector
{
void *sel_id;
const char *sel_types;
} *SEL;
typedef struct objc_object {
struct objc_class* class_pointer;
} *id;
typedef id (*IMP)(id, SEL, );
typedef char *STR; /* String alias */
typedef struct objc_class *MetaClass;
typedef struct objc_class *Class;
struct objc_class {
MetaClass class_pointer;
struct objc_class* super_class;
const char* name;
long version;
unsigned long info;
long instance_size;
struct objc_ivar_list* ivars;
struct objc_method_list* methods;
struct sarray * dtable;
struct objc_class* subclass_list;
struct objc_class* sibling_class;
struct objc_protocol_list *protocols;
void* gc_object_type;
};
typedef struct objc_protocol {
struct objc_class* class_pointer;
char *protocol_name;
struct objc_protocol_list *protocol_list;
struct objc_method_description_list *instance_methods, *class_methods;
} Protocol;
typedef void* retval_t;
typedef void(*apply_t)(void);
typedef union arglist {
char *arg_ptr;
char arg_regs[sizeof (char*)];
} *arglist_t;
typedef struct objc_ivar* Ivar_t;
typedef struct objc_ivar_list {
int ivar_count;
struct objc_ivar {
const char* ivar_name;
const char* ivar_type;
int ivar_offset;
} ivar_list[1];
} IvarList, *IvarList_t;
typedef struct objc_method {
SEL method_name;
const char* method_types;
IMP method_imp;
} Method, *Method_t;
typedef struct objc_method_list {
struct objc_method_list* method_next;
int method_count;
Method method_list[1];
} MethodList, *MethodList_t;
struct objc_protocol_list {
struct objc_protocol_list *next;
size_t count;
Protocol *list[1];
};
NSObject中唯一的成员为:Class isa;而Class是:typedef struct objec_class* Class;
如上的代码就是struct objec_class的结构实现,可以看出来它保存了父类指针、类名、各种类信息、实例的占内存大小、成员变量信息描述、成员函数信息描述等等。
本质上,ObjC就是用这个结构体,从C语言的基础上扩展了面向对象的特性,当然还存在很多其它详细的实现。
以我的理解,如下ObjC代码:
NSMyObject* obj = [[NSMyObject alloc] init];
[obj doSomething];
它的底层实现大致为:
1. 类实例的创建:
NSMyObject类对应一个struct objec_class结构体的实例,该实例中记录了NSMyObject的所有成员变量信息、成员函数信息。通过成员变量信息,计算出NSMyObject类实例所需占用的空间,以及各个变量对应的内存偏移量。这些信息都是编译时刻确定的,也就是说编译时刻就为NSMyObject类确定了一个信息完整的objec_class结构体指针。
当创建类的实例时,首先通过objec_class的信息分配内存空间,并确定好各成员变量的内存偏移值。那么,该实例就可以正常访问类的各个成员变量了。根父类中的Class isa指针指向NSMyObject类对应的objec_class结构体指针。
2. 函数调用
ObjC里面,把这个叫做“消息传递”。它实际上就是,通过NSObject中的isa指针,找到成员函数表,再把消息传递的参数拿过来和函数表中的成员一一对比。自己表里找不到就去父结构体里面找,直到找到为止。找到的就是函数的真正入口地址,传递适当的参数,就开始正常的C语言的函数调用了。
这样面向对象的特性基本就出来了。
关于Self
ObjC里面的Self和C++中的this不太一样,它也是函数的隐藏参数,当前为“-”成员方法时,self表示接收消息类的实例。当前为“+”类方法时,self表示当前类结构体指针。消息机制对应的C函数为:id objc_msgSend(id theReceiver, SEL theSelector, ...),那么Self其实就是通过receiver确定的值。
还有一些内容,链接:http://www.cocoachina.com/macdev/objc/2011/0124/2602.html
self 是函数的隐藏的参数,指向当前当前调用方法的类,另一个隐藏参数是 _cmd,代表当前类方法的 selector。这里只关注这个 self。super 是个啥?super 并不是隐藏的参数,它只是一个“编译器指示符”,它和 self 指向的是相同的消息接收者,拿上面的代码为例,不论是用 [self setName] 还是 [super setName],接收“setName”这个消息的接收者都是 PersonMe* me 这个对象。不同的是,super 告诉编译器,当调用 setName 的方法时,要去调用父类的方法,而不是本类里的。
当使用 self 调用方法时,会从当前类的方法列表中开始找,如果没有,就从父类中再找;而当使用 super 时,则从父类的方法列表中开始找。然后调用父类的这个方法