OC对象为什么不能动态增加属性?

Objective-C 是一门面向对象的编程语言。每一个对象都是一个类的实例。在 Objective-C 语言的内部,每一个对象都有一个名为 isa 的指针,指向该对象的类。每一个类描述了一系列它的实例的特点,包括成员变量的列表,成员函数的列表等。每一个对象都可以接受消息,而对象能够接收的消息列表是保存在它所对应的类中。
下面的代码展示了OC的类结构。

struct objc_class {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;

#if !__OBJC2__
    Class _Nullable super_class                              OBJC2_UNAVAILABLE;
    const char * _Nonnull name                               OBJC2_UNAVAILABLE;
    long version                                             OBJC2_UNAVAILABLE;
    long info                                                OBJC2_UNAVAILABLE;
    long instance_size                                       OBJC2_UNAVAILABLE;
    struct objc_ivar_list * _Nullable ivars                  OBJC2_UNAVAILABLE;
    struct objc_method_list * _Nullable * _Nullable methodLists                    OBJC2_UNAVAILABLE;
    struct objc_cache * _Nonnull cache                       OBJC2_UNAVAILABLE;
    struct objc_protocol_list * _Nullable protocols          OBJC2_UNAVAILABLE;
#endif

} OBJC2_UNAVAILABLE;
/* Use `Class` instead of `struct objc_class *` */

从上面代码可以看出,实际上,OC的类实际上是一个结构体。 isa 指针就是这个结构体的第一个成员变量,而类的其它成员变量依次排列在结构体中。


OC类结构.png

因为对象在内存中的排布可以看成一个结构体,该结构体的大小并不能动态变化。类的成员属性的大小是固定不变的,并且从下面objc_ivar的定义中,可以看到每个成员变量都会有在结构体中的相对偏移量还有所占用的空间,如果动态增加成员变量,会导致类的结构产生变化。因此,我们无法在运行时动态给对象增加成员变量。

struct objc_ivar {
    char * _Nullable ivar_name                               OBJC2_UNAVAILABLE;
    char * _Nullable ivar_type                               OBJC2_UNAVAILABLE;
    int ivar_offset                                          OBJC2_UNAVAILABLE;
#ifdef __LP64__
    int space                                                OBJC2_UNAVAILABLE;
#endif
}                                                            OBJC2_UNAVAILABLE;

相对的,对象的方法定义都保存在类的可变区域中。Objective-C 2.0 并未在头文件中将实现暴露出来,但在 Objective-C 1.0 中,我们可以看到方法的定义列表是一个名为 methodLists的指针的指针。通过修改该指针指向的指针的值,就可以实现动态地为某一个类增加成员方法。这也是Category实现的原理。

你可能感兴趣的:(OC对象为什么不能动态增加属性?)