六、isa走位图实例分析

isa流程图.png

LGPerson

@interface LGPerson : NSObject
- (void)sayNB;
+ (void)sayHappay;
@end
@implementation LGPerson
- (void)sayNB{
    NSLog(@"%s",__func__);
}
+ (void)sayHappay{
    NSLog(@"%s",__func__);
}
@end

LGStudent

@interface LGStudent : LGPerson
- (void)sayHello;
- (void)sayMaster;
+ (void)sayObjc;
@end

@implementation LGStudent
- (void)sayHello{
    NSLog(@"%s",__func__);
}

+ (void)sayObjc{
    NSLog(@"%s",__func__);
}
@end

方法调用

        LGStudent *student = [[LGStudent alloc] init];
        // 对象方法
        [student sayHello];
        [student sayNB];
        // [student sayMaster];
       
        // 类方法
        [LGStudent sayObjc];
        [LGStudent sayHappay];
        [LGStudent performSelector:@selector(sayEasy)]; 
图片.png

1. [LGStudent sayHappay];方法调用时,因为LGStudent中没有sayHappay方法, 则向上查找sayHappay方法, 父类LGPerson实现, 则调用,打印为+[LGPerson sayHappay]
2. [LGStudent performSelector:@selector(sayEasy)];调用时, 内部实际上使用runtime进行的方法调用, 和 [LGStudent sayEasy]是相同的, 不同的是在编译阶段,编译器不会报错, 这里因为LGStudentLGPerson中都未实现sayEasy方法, 则报错unrecognized selector
为了不改变两个类的结构, 我们可以使用分类来给类添加方法, 可以给LGStudentLGPerson添加分类, 就不详细说了,这里我们使用给NSObject来添加分类NSObject+LGCate

@interface NSObject (LGCate)
- (void)sayEasy;
@end
@implementation NSObject (LGCate)
- (void)sayEasy{
    NSLog(@"%s",__func__);
}

这样添加方法, 调用会报错吗?

答案: 会报错
|
|
|
|再思考一会
|
|
我们运行看下结果

图片.png

不会报错 并执行了NSObject中添加的分类方法

why?

图片.png

类方法查找流程和父类继承关系是一致的.
LGStudent类方法 存储在元类(LGStudent)里面, 在元类里的形式为实例方法,
查找不到则向上 元类(LGStudent)的父类元类LGPerson里查找,
查找不到则向上 跟元类(LGPerson)的父类根元类NSobject里查找,
查找不到则向上 跟元类(LGPerson)的父类NSobject里查找,
分类中有方法实现则调用, 所以不会报错

我们可以在NSObject中给任何子类拓展方法,而且不用区分是否是实例方法还是类方法

你可能感兴趣的:(六、isa走位图实例分析)