美文网首页
对象和方法的本质

对象和方法的本质

作者: ssRing | 来源:发表于2020-09-11 15:35 被阅读0次

    对象的本质

    Objective-C的对象本质其实是结构体。
    我们平时编写的objective-c代码,底层实现其实都是C/C++代码,所以Objective-C的面向对象都是基于C/C++的数据结构实现的,而其中Objective-C的对象和类则主要是基于C/C++的结构体来实现的。
    在main函数中定义一个简单对象:

    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            NSObject *obj = [[NSObject alloc] init];
        }
        return 0;
    }
    

    可以通过clang -rewrite-objc main.m -o main.cpp命令,将main.m文件进行重写,转换成对应的C/C++代码。
    在大约7700多行可以看到这段代码:

    struct NSObject_IMPL {
        Class isa; 
    };
    

    struct NSObject_IMPL就是NSObject的底层结构了,所以对象本质其实是结构体。
    随便在main函数某处输入Class,点击Jump to Definition,发现如下代码:

    typedef struct objc_class *Class;
    

    可以看出Class是结构体objc_class的别名,下面是objc_class源码的其中一部分:

    struct objc_class : objc_object {
        // Class ISA;
        Class superclass;
        cache_t cache;             // formerly cache pointer and vtable
        class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags
    
        class_rw_t *data() { 
            return bits.data();
        }
        ...
    }
    

    可以看出objc_class继承自结构体objc_object,于是找到objc_object的源码:

    struct objc_object {
    private:
        isa_t isa;
    
    public:
    
        // ISA() assumes this is NOT a tagged pointer object
        Class ISA();
    
        // getIsa() allows this to be a tagged pointer object
        Class getIsa();
    
        ...
    }
    

    objc_object中,第一个私有成员变量isa_t类型的isa,说明所有对象都包含一个类型为isa_t的isa指针。


    方法的本质

    Objective-C中方法的本质其实是发送消息。
    打开main.cpp文件,拉到文件末尾,可以看到:

    int main(int argc, const char * argv[]) {
        /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; 
            NSObject *obj = ((NSObject *(*)(id, SEL))(void *)objc_msgSend)((id)((NSObject *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("NSObject"), sel_registerName("alloc")), sel_registerName("init"));
        }
        return 0;
    }
    

    可以简单得出,方法的本质是通过objc_msgSend发送消息,其中第一个参数为id消息接受者,第二个参数为sel方法编号。
    OC方法函数调用,最终都会通过objc_msgSend进行消息转发,把对应方法编号SEL发送给对应的Class,查找到方法函数实现的指针IMP,找到函数实现的指针IMP就是找到对应的方法实现地址。
    通过SEL方法编号查找方法实现指针IMP,苹果提供了两种方案,一种是快速查找,利用缓存机制,使用汇编进行查找,一种是慢速查找,就是利用C、C++递归查找。
    因为objc_msgSend要求通过传入一个任意的SEL,最终找到方法实现的IMP指针,而在C语言中,不可能写一个函数去实现保留未知的参数,跳转任意的指针,而汇编语言可以直接通过寄存器操作,比C语言快很多,所以objc_msgSend是用汇编语言编写的。

    相关文章

      网友评论

          本文标题:对象和方法的本质

          本文链接:https://www.haomeiwen.com/subject/iodlsktx.html