美文网首页
面试题:分类中两个同名方法先执行哪个,都执行嘛?

面试题:分类中两个同名方法先执行哪个,都执行嘛?

作者: 常在士心 | 来源:发表于2021-10-09 14:22 被阅读0次

    主类和分类

    一. 需要解决的问题

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

    二. 测试环境搭建

    1. 创建下面这些测试用的类

      image
    2. 加入一个pch文件方便打印

    #ifdef DEBUG
    #define LGLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ## __VA_ARGS__);
    #else
    #define LGLog(...)
    #endif
    --------------------- 
    
    

    主要内容

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

    • 我们在主类和各分类中重写+load方法
    //Person
    + (void)load{
        LGLog();
    }
    //-------------
    //Son
    + (void)load{
        LGLog();
    }
    //-------------
    Person+A
    + (void)load{
        LGLog();
    }
    //-------------
    Person+B
    + (void)load{
        LGLog();
    }
    //-------------
    Person+C
    + (void)load{
        LGLog();
    }
    --------------------- 
    
    
    • 打印输出

      image
    • 调整分类的编译顺序在打印

      image

    2. 结论

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

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

    • 我们在主类中加入普通的类方法(+commonClsMethod)和实例方法(-commonInstanceMethod)
    • 在分类中也重写这两个方法
    + (void)commonClsMethod{
        LGLog();
    }
    - (void)commonInstanceMethod{
       LGLog();
    }
    
    
    1. 正常结果

      image
    2. 分类文件警告

      image

    结论

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

    探究+ initialize方法的调用

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

    结论

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

    总结

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

    作者:武一顶顶
    链接:https://www.jianshu.com/p/3907eed7f9f3
    来源:简书

    demo

    转载 https://blog.csdn.net/appleLg/article/details/79931742

    相关文章

      网友评论

          本文标题:面试题:分类中两个同名方法先执行哪个,都执行嘛?

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