zoukankan      html  css  js  c++  java
  • Objective-C的动态设计

    我们都知道,Objective-C是一门动态语言,它的Runtime机制往往能让我们实现一些黑魔法。那么,这门语言是如何实现它的动态特征的呢?

    下面我们来刨根问底看个究竟。

    在Objective-C中,我们用到的几乎所有的类都是NSObject类的子类,NSObject类的定义如下:

    @interface NSObject <NSObject> {
    Class isa;
    }

    就一个Class 类型的isa实例变量,Class是什么类型?我们切入看一下

    Class 是一个 struct objc_class *的指针,struct objc_class定义如下:

    struct objc_class {

        Class isa  OBJC_ISA_AVAILABILITY;

    #if !__OBJC2__

        Class super_class                                        OBJC2_UNAVAILABLE;

        const char *name                                         OBJC2_UNAVAILABLE;

        long version                                             OBJC2_UNAVAILABLE;

        long info                                                OBJC2_UNAVAILABLE;

        long instance_size                                       OBJC2_UNAVAILABLE;

        struct objc_ivar_list *ivars                             OBJC2_UNAVAILABLE;

        struct objc_method_list **methodLists                    OBJC2_UNAVAILABLE;

        struct objc_cache *cache                                 OBJC2_UNAVAILABLE;

        struct objc_protocol_list *protocols                     OBJC2_UNAVAILABLE;

    #endif

    } OBJC2_UNAVAILABLE;

    看到这里大家可能又晕了,怎么又有一个isa?这些isa是什么?之间有什么联系?

    其实,Objective-C中任何类定义都是一个对象。即在程序启动的时候任何类定义都对应于一块内存。在编译的时候,编译器会给每一个类生成一个且只生成一个”描述其定义的对象”,也就是苹果公司说的类对象(class object),他是一个单例(singleton)。每个实例的isa指针就会指向它对应的类对象。而这个类对象会存储它的实例的相关信息,包括实例方法、实例变量、实现的协议等。

    从上面的结构体中我们可以看到,类对象也拥有一个isa指针,这个指针又指向何处呢?

    我们知道,对象都是由类实例化而来的,那么类对象也是某个类实例化而来的,类对象的isa指针就指向这个实例化他的类的对象,我们称这个类为元类,元类存储了类的相关信息(其中主要包括类方法列表)。

    还是有些不明白?下面这个图标可能会有些帮助:

    也就是说,在编译的时候,编译器会对每一个类生成一个类对象和一个元类对象,来存储这个类的相关信息。当我们实例化一个对象的时候,是根据这个类对象包含的信息实例化的。

    既然这类是一个对象,那么,它的成员值就可以改变,这就个了我们动态改变一个类的无线可能。

    我们可以动态的向方法列表中添加方法、甚至新添加一个类等等。

    但是我们不能动态的添加实例变量,因为实例变量存储在ivars中,而ivars是struct objc_ivar_list *类型,在编译完成后类对象的存储空间不能改变,也就意味着ivars不能改变,因而不能动态的添加实例变量。这也是分类中不能添加实例变量的原因。

    可能有的童鞋会问,那为什么可以添加实例方法呢?

    从类的结构体中可以发现,methodLists是struct objc_method_list **类型的,意味着类对象中只是存了一个列表的指针,而实际方法列表的容器并不存储在类对象中。

    参考文章:Objective-C对象之类对象和元类对象

  • 相关阅读:
    webapp之路--meta标签format-detection、apple-mobile-web-app-capable
    js 进行年月日时间差计算
    JS手机邮箱身份证号码的正则验证以及通过身份证号码获取出生年月日
    react setState()方法可以只修改一个对象的部分属性
    js获取当前时间格式YYYY/MM/DD
    提高CSS开发能力的技巧集
    JavaScript专业规则12条
    为什么大型网站前端使用PHP后台逻辑用Java
    Cookie与Session的区别
    2016年JavaScript技术栈展望
  • 原文地址:https://www.cnblogs.com/yueyuanyueyuan/p/7307435.html
Copyright © 2011-2022 走看看