美文网首页
Objective-C 中的类

Objective-C 中的类

作者: 一半晴天 | 来源:发表于2018-06-16 16:36 被阅读20次

    此文实际成于 2015/07/29

    Objc explain Classes and metaclasses

    Objective-C 是基于类的对象系统。

    1. 每一个对象都是某一个类的一个实例。

    2. 对象的 isa 指针指向它的类。

    3. 类描述对象的数据信息如:分配的内存大小,ivar类型及布局。

    4. 类同时描述了对象的行为如:它所响应的选择器;它所实现的实例方法。

    5. 类的方法列表是实例方法的集合,对象能够响应选择器。
      当发送一个消息给对象时,objc_msgSend()查询类(或超类,如果有的话)的方法列表,来决定调用哪一个方法。

    6. 每一个 Objective-C 类同样是一个对象。 它有一个isa指针及其他数据,
      同样能响应选择器。当你像这样 [NSObject alloc] 调用一个类方法(class method)时。实际是你是在发送消息给哪一个类对象。

    7. 因为一个类也是一个对象,它就必须是某一个元类(meta class)的实例.

    metaclass 是类对象的描述。正如类是普通的实例的描述。
    实际上,

    1. 类的方法列表就是类方法列表,类对象响应的选择器。
    2. 当你发送一个消息给一个类(一个元类的实例),objc_msgSend() 查找元类(或其超类,如果有的话)的方法列表来决定调用哪一个方法。

    正如实例方法以类来描述以代表类对象。类方法以元类来描述来代表实例对象。

    什么是元类?

    元类是根类的元类的实例。 根元类本身是根根元类的一个实例。isa链在这里以一个循环结尾: 实例到类对元类到根类到它自身。元类的 isa指针的行为一般不影响什么的。因为在现实中没有人发送信息给元类对象。

    最重要的是一个元类的超类。元类的超类链跟类的越类链是并行的,所以类方法的继承也跟实例方法的继承是并行的。并且根元类的越类是根类,因此每一个类对象响应根类的实例方法。
    最后,类对象是根类的或其子类的实例,正如其他对象一个。

    如下图:


    objc class and meta class

    对应代码如下:

        // Connect to superclasses and metaclasses
        cls->initClassIsa(meta);
        if (superclass) {
            meta->initClassIsa(superclass->ISA()->ISA());
            cls->superclass = superclass;
            meta->superclass = superclass->ISA();
            addSubclass(superclass, cls);
            addSubclass(superclass->ISA(), meta);
        } else {
            meta->initClassIsa(meta);
            cls->superclass = Nil;
            meta->superclass = cls;
            addSubclass(cls, meta);
        }
    
    

    上面的 对于isa的设置主要在 cls->initClassIsa(meta) 方法中体现 。

    inline void 
    objc_object::initClassIsa(Class cls)
    {
        initIsa(cls);
    }
    

    然后很多与初始化isa操作,最后都调用到了initIsa(cls) 方法上来。

    对于非 Tagged Pointer 的 ISA 类型,
    其初始 化操作就是一个简单的赋值操作:

    inline void 
    objc_object::initIsa(Class cls)
    {
        assert(!isTaggedPointer()); 
        isa = (uintptr_t)cls; 
    }
    

    对于 Tagged Pointer 实现的

    其实现稍微复杂一些,如下 :

    
    inline void 
    objc_object::initIsa(Class cls)
    {
        initIsa(cls, false, false);
    }
    
    inline void 
    objc_object::initClassIsa(Class cls)
    {
        if (DisableIndexedIsa) {
            initIsa(cls, false, false);
        } else {
            initIsa(cls, true, false);
        }
    }
    
    inline void
    objc_object::initProtocolIsa(Class cls)
    {
        return initClassIsa(cls);
    }
    
    inline void 
    objc_object::initInstanceIsa(Class cls, bool hasCxxDtor)
    {
        assert(!UseGC);
        assert(!cls->requiresRawIsa());
        assert(hasCxxDtor == cls->hasCxxDtor());
    
        initIsa(cls, true, hasCxxDtor);
    }
    
    inline void 
    objc_object::initIsa(Class cls, bool indexed, bool hasCxxDtor) 
    { 
        assert(!isTaggedPointer()); 
        
        if (!indexed) {
            isa.cls = cls;
        } else {
            assert(!DisableIndexedIsa);
            isa.bits = ISA_MAGIC_VALUE;
            // isa.magic is part of ISA_MAGIC_VALUE
            // isa.indexed is part of ISA_MAGIC_VALUE
            isa.has_cxx_dtor = hasCxxDtor;
            isa.shiftcls = (uintptr_t)cls >> 3;
        }
    }
    
    
    

    小结

    当像一个对象发送消息时,方法的查找以对象的isa指针开始,然后继续到其超类链。
    实例方法在类中定义
    类方法在元类定义加上根类(非元类)。

    类方法与实例方法的查找

    按上面的说法,类方法其实是类对象isa所指向的元类的实例方法。
    因此其实现如下 :

    /***********************************************************************
    * class_getClassMethod.  Return the class method for the specified
    * class and selector.
    **********************************************************************/
    Method class_getClassMethod(Class cls, SEL sel)
    {
        if (!cls  ||  !sel) return nil;
    
        return class_getInstanceMethod(cls->getMeta(), sel);
    }
    

    新类的内存分配

    /***********************************************************************
    * objc_allocateClassPair
    * fixme
    * Locking: acquires runtimeLock
    **********************************************************************/
    Class objc_allocateClassPair(Class superclass, const char *name, 
                                 size_t extraBytes)
    {
        Class cls, meta;
    
        rwlock_write(&runtimeLock);
    
        // Fail if the class name is in use.
        // Fail if the superclass isn't kosher.
        if (getClass(name)  ||  !verifySuperclass(superclass, true/*rootOK*/)) {
            rwlock_unlock_write(&runtimeLock);
            return nil;
        }
    
        // Allocate new classes.
        cls  = alloc_class_for_subclass(superclass, extraBytes);
        meta = alloc_class_for_subclass(superclass, extraBytes);
    
        // fixme mangle the name if it looks swift-y?
        objc_initializeClassPair_internal(superclass, name, cls, meta);
    
        rwlock_unlock_write(&runtimeLock);
    
        return cls;
    }
    

        cls  = alloc_class_for_subclass(superclass, extraBytes);
        meta = alloc_class_for_subclass(superclass, extraBytes);
    

    可以看出,类和元类的继承是并行的。

    整个类复杂的关联就在下面这大段代码中体现:

    /***********************************************************************
    * objc_initializeClassPair
    * Locking: runtimeLock must be write-locked by the caller
    **********************************************************************/
    
    // &UnsetLayout is the default ivar layout during class construction
    static const uint8_t UnsetLayout = 0;
    
    static void objc_initializeClassPair_internal(Class superclass, const char *name, Class cls, Class meta)
    {
        rwlock_assert_writing(&runtimeLock);
    
        class_ro_t *cls_ro_w, *meta_ro_w;
    
        cls->cache.setEmpty();
        meta->cache.setEmpty();
        
        cls->setData((class_rw_t *)_calloc_internal(sizeof(class_rw_t), 1));
        meta->setData((class_rw_t *)_calloc_internal(sizeof(class_rw_t), 1));
        cls_ro_w   = (class_ro_t *)_calloc_internal(sizeof(class_ro_t), 1);
        meta_ro_w  = (class_ro_t *)_calloc_internal(sizeof(class_ro_t), 1);
        cls->data()->ro = cls_ro_w;
        meta->data()->ro = meta_ro_w;
    
        // Set basic info
    
        cls->data()->flags = RW_CONSTRUCTING | RW_COPIED_RO | RW_REALIZED | RW_REALIZING;
        meta->data()->flags = RW_CONSTRUCTING | RW_COPIED_RO | RW_REALIZED | RW_REALIZING;
        cls->data()->version = 0;
        meta->data()->version = 7;
    
        cls_ro_w->flags = 0;
        meta_ro_w->flags = RO_META;
        if (!superclass) {
            cls_ro_w->flags |= RO_ROOT;
            meta_ro_w->flags |= RO_ROOT;
        }
        if (superclass) {
            cls_ro_w->instanceStart = superclass->unalignedInstanceSize();
            meta_ro_w->instanceStart = superclass->ISA()->unalignedInstanceSize();
            cls->setInstanceSize(cls_ro_w->instanceStart);
            meta->setInstanceSize(meta_ro_w->instanceStart);
        } else {
            cls_ro_w->instanceStart = 0;
            meta_ro_w->instanceStart = (uint32_t)sizeof(objc_class);
            cls->setInstanceSize((uint32_t)sizeof(id));  // just an isa
            meta->setInstanceSize(meta_ro_w->instanceStart);
        }
    
        cls_ro_w->name = _strdup_internal(name);
        meta_ro_w->name = _strdup_internal(name);
    
        cls_ro_w->ivarLayout = &UnsetLayout;
        cls_ro_w->weakIvarLayout = &UnsetLayout;
    
        // Connect to superclasses and metaclasses
        cls->initClassIsa(meta);
        if (superclass) {
            meta->initClassIsa(superclass->ISA()->ISA());
            cls->superclass = superclass;
            meta->superclass = superclass->ISA();
            addSubclass(superclass, cls);
            addSubclass(superclass->ISA(), meta);
        } else {
            meta->initClassIsa(meta);
            cls->superclass = Nil;
            meta->superclass = cls;
            addSubclass(cls, meta);
        }
    }
    
    
    

    Objective-C 的类是以 struct objc_class来实现的。
    而其继承自 struct objc_objectid

    struct objc_class有新旧两种定义。老的定义虽然很 OS X 10.5 就不再用了。但是有助于帮助我们理解 struct objc_class有什么 。

    类的老的运行时定义

    老的定义在 objc-runtime-old.h中。

    struct objc_class : objc_object {
        Class superclass;
        const char *name;
        uint32_t version;
        uint32_t info;
        uint32_t instance_size;
        struct old_ivar_list *ivars;
        struct old_method_list **methodLists;
        Cache cache;
        struct old_protocol_list *protocols;
        // CLS_EXT only
        const uint8_t *ivar_layout;
        struct old_class_ext *ext;
    

    上面的 Class类型,是:
    typedef struct objc_class *Class
    它们都在 objc-private.h中有定义:

    struct objc_class;
    struct objc_object;
    
    typedef struct objc_class *Class;
    typedef struct objc_object *id;
    

    也就是说objc_class实现了一种单链表的结构。也可以说它是类的单继承结构。
    Class好比是链表结构中的一个Node

    从上面的结构定义可以看出老式的类定义有哪些内容呢?

    - `Class superclass` 其指向的超类
    - `const char *name` 类名
    - `version` 类的版本
    - `info` 类信息
    - `instance_size` 类对象实例的大小
    - `struct objc_ivar_list *ivars` 实例变量列表
    - `struct objc_method_list **methodLists` 实例方法列表
    - `struct objc_cache *cache` 方法解析缓存的Hash 表
    - `struct objc_protocol_list *protocols` 类实例实现的协议列表
    
    也不能忘了其公开的头文件的声明 `runtime.h`
    中将`isa`字段也包括在内。但是实现是在`struct objc_object`中声明的。
    
    ```c
    struct objc_class {
    Class isa  OBJC_ISA_AVAILABILITY;
    }
    ```
    
    `isa` 表明一个实际的对象实际上是一个什么类。实际上每一个 objc 的对象都 是一个一个`isa`指针开始的,要不 objc 运行时不知道怎么处理这一块内存,这一个对象。
    

    新的类定义

    其基本声明如下 :

    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();
         }
     }
    

    新的实现更复杂高效。

    上面介绍的实例变量列表,方法列表,协议列表都由 class_rw_t结构来实现了。

    其声明如下 :

    struct class_rw_t {
        uint32_t flags;
        uint32_t version;
    
        const class_ro_t *ro;
    
        union {
            method_list_t **method_lists;  // RW_METHOD_ARRAY == 1
            method_list_t *method_list;    // RW_METHOD_ARRAY == 0
        };
        struct chained_property_list *properties;
        const protocol_list_t ** protocols;
    
        Class firstSubclass;
        Class nextSiblingClass;
    
        char *demangledName;
    
    

    其中 const class_ro_t *ro; 存储了方法列表,协议列表,实例变量列表的关键信息。

    struct class_ro_t {
        uint32_t flags;
        uint32_t instanceStart;
        uint32_t instanceSize;
    #ifdef __LP64__
        uint32_t reserved;
    #endif
    
        const uint8_t * ivarLayout;
        
        const char * name;
        const method_list_t * baseMethods;
        const protocol_list_t * baseProtocols;
        const ivar_list_t * ivars;
    
        const uint8_t * weakIvarLayout;
        const property_list_t *baseProperties;
    };
    

    参考文档

    1. Friday Q&A 2009-03-13: Intro to the Objective-C Runtime
    2. [objc explain] Classes and metaclasses

    相关文章

      网友评论

          本文标题:Objective-C 中的类

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