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

对象与方法的本质

作者: Vency_ | 来源:发表于2019-04-17 18:01 被阅读0次

    方法:

    通过前面一篇 从 MachO 加载到对象创建! 可以了解到 allocinit 方法的底层, 接下来看方法的实质:

    定义类 WXPerson, 包含方法 run;
    创建 person 对象:

    WXPerson * person = [[WXPerson all] init];
    [person run];
    

    通过编译器编译来看对象及方法的实质:
    通过终端命令 clang -rewrite-objc main.m 可以获得同级目录下 main.cpp文件, 查看文件发现, 上面创建对象及调用方法被编译成如下代码:
    由于代码太长选择图片格式:

    可以看到很多类型强转, 去掉类型强转:

    WXPerson * person = objc_msgSend(
                                    objc_msgSend(
                                                objc_getClass("WXPerson"), 
                                                sel_registerName("alloc")), 
                                    sel_registerName("init"));
        objc_msgSend(person, 
                     sel_registerName("run"));
    

    可以看到:

    • 每次方法的调用都被编译成了消息发送 objc_msgSend;
    • 调用 alloc 类方法是通过 objc_getClass 获取类对象进行调用;
    • @selector() 会编译为 sel_registerName 方法, 向编译器注册一个方法;

    补充: 由于该方法调用非常频繁, 且 C / C++ 方法不能动态保存方法的参数, 需要通过汇编通过寄存器读取动态参数, 所以苹果把该方法用汇编实现(具体见 libobjc.A.dylib -> objc-msg-*.s):
    前面文章已有涉及: +load VS +initialize

    对象:

    查看上面编译好的 main.cpp 文件:

    typedef struct objc_object WXPerson;
    typedef struct {} _objc_exc_WXPerson;
    
    struct WXPerson_IMPL {
        struct NSObject_IMPL NSObject_IVARS;
    };
    
    struct NSObject_IMPL {
        Class isa;
    };
    

    可以发现 WXPerson类被编译为 typedef struct objc_object WXPerson 结构体
    objc_object 定义如下:

    typedef struct objc_class *Class;
    
    struct objc_object {
        Class _Nonnull isa __attribute__((deprecated));
    };
    
    typedef struct objc_object *id;
    
    typedef struct objc_selector *SEL;
    
    

    至此可以看出:

    • 对象的本质是结构体;
    • 对象包含一个指向 objc_class 结构体的 isa;
    • 所以 id 可以代表一个对象;

    相关文章

      网友评论

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

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