OjbC中NSObject面向对象特性的底层实现

#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 时,则从父类的方法列表中开始找。然后调用父类的这个方法