runtime详解(四)-category底层原理

本文详细介绍了Objective-C的Category特性,包括它的用途、本质和加载过程。Category允许在不修改原有类源码的情况下扩展类的功能,主要用于分类方法、模拟多继承等。文章探讨了Category与类的加载、+load方法的关系,以及如何利用Category实现关联对象,提供了深入理解Category的视角。
摘要由CSDN通过智能技术生成

简介

Category(分类) 是 Objective-C 2.0 添加的语言特性,主要作用是为已经存在的类添加方法。Category 可以做到在既不子类化,也不侵入一个类的源码的情况下,为原有的类添加新的方法,从而实现扩展一个类或者分离一个类的目的。在日常开发中我们常常使用 Category 为已有的类扩展功能。

虽然继承也能为已有类增加新的方法,而且还能直接增加属性,但继承关系增加了不必要的代码复杂度,在运行时,也无法与父类的原始方法进行区分。所以我们可以优先考虑使用自定义 Category(分类)。

通常 Category(分类)有以下几种使用场景:

把类的不同实现方法分开到不同的文件里。
声明私有方法。
模拟多继承。
将 framework 私有方法公开化。

分类和扩展

extension看起来很像一个匿名的category,但是extension和有名字的category几乎完全是两个东西。 extension在编译期决议,它就是类的一部分,在编译期和头文件里的@interface以及实现文件里的@implement一起形成一个完整的类,它伴随类的产生而产生,亦随之一起消亡。extension一般用来隐藏类的私有信息,你必须有一个类的源码才能为一个类添加extension,所以你无法为系统的类比如NSString添加extension。(详见 2)

但是category则完全不一样,它是在运行期决议的。 就category和extension的区别来看,我们可以推导出一个明显的事实,extension可以添加实例变量,而category是无法添加实例变量的(因为在运行期,对象的内存布局已经确定,如果添加实例变量就会破坏类的内部布局,这对编译型语言来说是灾难性的)。

Category本质

在objc-private中找到了它的结构体

struct category_t {
    const char *name;    //分类的名字
    classref_t cls;         //所属的类
    struct method_list_t *instanceMethods;  //分类中的实例方法
    struct method_list_t *classMethods;  //分类中的类方法
    struct protocol_list_t *protocols;   //分类实现的协议
    struct property_list_t *instanceProperties;   //分类中的属性
    // Fields below this point are not always present on disk.   
    struct property_list_t *_classProperties;      //分类中的属性
    

写一个demo看看c++代码

在这里插入图片描述
在这里插入图片描述
转为c++后查找结构体
在这里插入图片描述
顺便还验证了runtime(三)中的结论,在编译期间,class结构体中的方法列表等存放在class_ro_t当中,class_rw_t在runtime初始化后才有的。
在这里插入图片描述
这是结构体的赋值语句。
分类数组在这里插入图片描述
也能找到对应的方法列表和属性列表,分类中添加的东西存放在_OBJC_KaTeX parse error: Expected group after '_' at position 33: …E_METHODS_xxxxx_̲_xxxxAddition中
在这里插入图片描述
存放的正是我们刚刚在分类中所写的。

小结

1)、首先编译器生成了实例方法列表
OBJC$CATEGORY_INSTANCE_METHODS_MyClass$MyAddition和属性列表_OBJC$ PROP_LIST_MyClass$MyAddition两者的命名都遵循了公共前缀+类名+category名字的命名方式,而且实例方法列表里面填充的正是我们在这个category里面写的方法,而属性列表里面填充的也正是我们在分类里添加的属性。还有一个需要注意到的事实就是category的名字用来给各种列表以及后面的category结构体本身命名,而且有static来修饰,所以在同一个编译单元里我们的category名不能重复,否则会出现编译错误。
2)、其次,编译器生成了category本身_OBJC C A T E G O R Y M y C l a s s CATEGORY_MyClass CATEGORYM

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值