OC底层05:类结构分析

2020-09-20  本文已影响0人  木扬音

在谈及面向对象编程的时候,总是离不开 对象对象 是对客观事物的抽象, 是对 对象 的抽象。它们的关系是,对象 的实例,对象 的模板。
在OC中对象的信息存储在中,那么是以什么样的结果存在的呢,我们可以在objc的源码中找到下面代码,从中可以发现objc_class 是继承objc_object 的,也就是说 也是一个对象。这也是OC中万物皆对象的由来。因其继承自 objc_object ,自然默认就含有了 objc_object 的成员 isa

isa和继承

image.png

我们可以通过isa流程和继承关系图发现

isa的走向有以下几点说明:

superclass(即继承关系)的走向也有以下几点说明:

-【注意】实例对象之间没有继承关系,之间有继承关系

/// Represents an instance of a class.
struct objc_object {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;
};
struct objc_class : objc_object {
    // Class ISA;//8字节
    Class superclass; //8字节
    cache_t cache; //8字节            // formerly cache pointer and vtable
    class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags
}

cache_t

我们进入cache_t,发现主要有如下几个属性

struct cache_t {
#if CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_OUTLINED
    explicit_atomic<struct bucket_t *> _buckets; // 是一个结构体指针类型,占8字节
    explicit_atomic<mask_t> _mask; //是mask_t 类型,而 mask_t 是 unsigned int 的别名,占4字节
#elif CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_HIGH_16
    explicit_atomic<uintptr_t> _maskAndBuckets; //是指针,占8字节
    mask_t _mask_unused; //是mask_t 类型,而 mask_t 是 uint32_t 类型定义的别名,占4字节
    
#if __LP64__
    uint16_t _flags;  //是uint16_t类型,uint16_t是 unsigned short 的别名,占 2个字节
#endif
    uint16_t _occupied; //是uint16_t类型,uint16_t是 unsigned short 的别名,占 2个字节

通过计算cache_t中属性大小为16字节
所以我们可以通过获取的首地址,通过平移32字节来获取bits中的内容

获取bits

准备工作

定义一个继承自NSObject的类YPPerson

@interface YPPerson : NSObject
{
    NSString *hobby;
}
@property (nonatomic, copy) NSString *yp_name;
- (void)sayHello;
+ (void)sayBye;
@end

@implementation YPPerson
- (void)sayHello{
}

+ (void)sayBye{
}
@end

通过lldb调试打印bits信息

image.png

获取属性列表

class_data_bits_t方法class_rw_t,点进去class_rw_t中提供获取了属性列表、方法列表等方法

  const method_array_t methods() const {
        auto v = get_ro_or_rwe();
        if (v.is<class_rw_ext_t *>()) {
            return v.get<class_rw_ext_t *>()->methods;
        } else {
            return method_array_t{v.get<const class_ro_t *>()->baseMethods()};
        }
    }

    const property_array_t properties() const {
        auto v = get_ro_or_rwe();
        if (v.is<class_rw_ext_t *>()) {
            return v.get<class_rw_ext_t *>()->properties;
        } else {
            return property_array_t{v.get<const class_ro_t *>()->baseProperties};
        }
    }

    const protocol_array_t protocols() const {
        auto v = get_ro_or_rwe();
        if (v.is<class_rw_ext_t *>()) {
            return v.get<class_rw_ext_t *>()->protocols;
        } else {
            return protocol_array_t{v.get<const class_ro_t *>()->baseProtocols};
        }
    }

所以我们在刚刚获取到的bits信息基础上,通过class_rw_t提供的方法,我们可以继续打印出属性列表

获取属性列表

获取方法列表

image.png
上一篇下一篇

猜你喜欢

热点阅读