项目作者: LGLee

项目描述 :
这是一个categoryDemo的探究,辅助blog的Demo:https://blog.csdn.net/appleLg/article/details/79931742
高级语言: Objective-C
项目地址: git://github.com/LGLee/categoryDemo.git
创建时间: 2018-04-13T09:09:59Z
项目社区:https://github.com/LGLee/categoryDemo

开源协议:Apache License 2.0

下载


categoryDemo

这是一个categoryDemo的探究,辅助blog的Demo:https://blog.csdn.net/appleLg/article/details/79931742

主类和分类

时间有限,可以直接看结论,或者联系我企鹅qq:549931192

一. 需要解决的问题

  1. 主类和分类中普通方法的调用顺序?
  2. 同一个主类的两个分类中的同名方法调用顺序?
  3. 分类中+load方法的调用顺序?
  4. 分类中+initialize 方法的调用顺序?

    二. 测试环境搭建

  5. 创建下面这些测试用的类
    这里写图片描述
  6. 加入一个pch文件方便打印
  1. #ifdef DEBUG
  2. #define LGLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ## __VA_ARGS__);
  3. #else
  4. #define LGLog(...)
  5. #endif

主要内容

1. 主类,子类和分类中的+load方法的加载

  • 我们在主类和各分类中重写+load方法
  1. //Person
  2. + (void)load{
  3. LGLog();
  4. }
  5. //-------------
  6. //Son
  7. + (void)load{
  8. LGLog();
  9. }
  10. //-------------
  11. Person+A
  12. + (void)load{
  13. LGLog();
  14. }
  15. //-------------
  16. Person+B
  17. + (void)load{
  18. LGLog();
  19. }
  20. //-------------
  21. Person+C
  22. + (void)load{
  23. LGLog();
  24. }
  • 打印输出
    这里写图片描述
  • 调整分类的编译顺序在打印
    这里写图片描述

2. 结论

  • +load方法的调用是在main() 函数之前,并且不需要主动调用,就是说程序启动会把所有的文件加载
  • 主类和分类的都会加载调用+load方法
  • 主类与分类的加载顺序是:主类优先于分类加载,无关编译顺序
  • 分类间的加载顺序取决于编译的顺序:编译在前则先加载,编译在后则后加载
  • 规则是父类优先于子类, 子类优先于分类(父类>子类>分类)

    1. 探究主类和分类的普通同名方法调用顺序

  • 我们在主类中加入普通的类方法(+commonClsMethod)和实例方法(-commonInstanceMethod)
  • 在分类中也重写这两个方法
  1. + (void)commonClsMethod{
  2. LGLog();
  3. }
  4. - (void)commonInstanceMethod{
  5. LGLog();
  6. }
  1. 正常结果
    这里写图片描述
  2. 分类文件警告
    这里写图片描述

    结论

  • 普通的方法中, 分类同名方法会覆盖主类的方法
  • 多个分类中的同名方法会只执行一个,即后编译的分类里面的方法会覆盖所有前面的同名方法(可以通过调换编译顺序来获得这个结论)
  • 分类中的方法名和主类方法名一样会报警告,大概就是说分类中实现的方法主类已经实现了
  • 可以把声明写在主类, 实现写在分类,这样也能调用到分类里面的代码
  • 同样可以把声明和实现写在不同的分类文件中,还是能找到的, 不过主类要相同

    探究+ initialize方法的调用

  • 调用子类的+ (void)initialize方法
  1. [[Son new] commonInstanceMethod];

这里写图片描述

结论

  • 当第一次用到类的时候, 如果重写了+ initialize方法,会去调用
  • 当调用子类的+ initialize方法时候, 先调用父类的,如果父类有分类, 那么分类的+ initialize会覆盖掉父类的, 和普通方法差不多
  • 父类的+ initialize不一定会调用, 因为分类可能重写了它
  • 普通方法的优先级:分类>子类>父类

    总结

  1. 普通方法的优先级: 分类> 子类 > 父类, 优先级高的同名方法覆盖优先级低的
  2. +load方法的优先级: 父类> 子类> 分类
  3. +load方法是在main() 函数之前调用,所有的类文件都会加载,包括分类
  4. +load方法不会被覆盖
  5. 同一主类的不同分类中的普通同名方法调用, 取决于编译的顺序, 后编译的文件中的同名方法会覆盖前面所有的,包括主类. +load方法的顺序也取决于编译顺序, 但是不会覆盖
  6. 分类中的方法名和主类方法名一样会报警告, 不会报错
  7. 声明和实现可以写在不同的分类中, 依然能找到实现
  8. 当第一次用到类的时候, 如果重写了+ initialize方法,会去调用
  9. 当调用子类的+ initialize方法时候, 先调用父类的,如果父类有分类, 那么分类的+ initialize会覆盖掉父类的, 和普通方法差不多
  10. 父类的+ initialize不一定会调用, 因为有可能父类的分类重写了它

    demo