self 与 super
思考如下代码的打印结果?
@interface Person : NSObject @end @implementation Person @end @interface Student : Person @end @implementation Student - (instancetype)init { if (self = [super init]) { NSLog(@"%@", [self class]); //打印结果:Student NSLog(@"%@", [self superclass]); //Person NSLog(@"%@", [super class]); //Student NSLog(@"%@", [super superclass]); //Person } return self; } @end
打印结果:
Student Person Student Person
1. 利用以下命令看下[super class]的底层调用:
xcrun -sdk iphoneos clang -arch arm64 -F Foundation.framework -rewrite-objc main.m -o main.cpp
2. 可以看到[super class]转换为了如下代码:
((Class (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("Student"))}, sel_registerName("class"));
简化后如下:
(objc_msgSendSuper)({self, class_getSuperclass(objc_getClass("Student"))}, @selector(class));
3. 通过源码看下objc_msgSendSuper的底层实现如下
objc_msgSendSuper(struct objc_super * _Nonnull super, SEL _Nonnull op, ...)
可以看到第一个参数为objc_super结构体,第二个参数为SEL类型,其中objc_super的结构如下:
struct objc_super { __unsafe_unretained _Nonnull id receiver; // 消息接收者 __unsafe_unretained _Nonnull Class super_class; // 消息接收者的父类 };
第一个成员为receiver也就是消息接收者,第二个参数为Class;4. 通过[super class]的简化后代码可知:
(objc_msgSendSuper)({self, class_getSuperclass(objc_getClass("Student"))}, @selector(class));
其中class的实现为:
- (Class)class { return object_getClass(self); }
receiver参数值为self,super_class参数值为Student类对象的父类,也就是Person,SEL为class,意思为调用class方法的时候从Person类里面去找,消息接收者依旧为当前类,结合class的内部实现,也就是self的class对象,故此处为Student;
[super superclass]同理,消息接收者receiver参数值为self,super_class参数值为Student类对象的父类,也就是Person,SEL为superclass,故此处为Student的父类,也就是Person;
总结无论是self或者super真正调用的对象都是一样的,也就是消息接收者是一致的,只是方法查找的位置不一样,self是从当前类结构中开始查找,super是从父类中查找,但方法的接收者都是当前类或者当前类的对象;isKindOfClass: 与 isMemberOfClass: 思考如下代码的打印结果?
@interface Person : NSObject @end @implementation Person @end int main(int argc, const char * argv[]) { @autoreleasepool { Person *person = [Person new]; BOOL ret1 = [person isKindOfClass:[NSObject class]]; //打印结果: 1 BOOL ret2 = [person isKindOfClass:[Person class]]; //打印结果: 1 BOOL ret3 = [person isMemberOfClass:[NSObject class]]; //打印结果: 0 BOOL ret4 = [person isMemberOfClass:[Person class]]; //打印结果: 1 NSLog(@"%d - %d - %d - %d", ret1, ret2, ret3, ret4); BOOL ret5 = [[NSObject class] isKindOfClass:[NSObject class]]; //打印结果: 1 BOOL ret6 = [[NSObject class] isMemberOfClass:[NSObject class]]; //打印结果: 0 BOOL ret7 = [[Person class] isKindOfClass:[Person class]]; //打印结果: 0 BOOL ret8 = [[Person class] isMemberOfClass:[Person class]]; //打印结果: 0 BOOL ret9 = [[Person class] isKindOfClass:[NSObject class]]; //打印结果: 1 NSLog(@"%d - %d - %d - %d - %d", ret5, ret6, ret7, ret8, ret9); } return 0; }
打印结果:
1 - 1 - 0 - 1 1 - 0 - 0 - 0 - 1
isKindOfClass: 与 isMemberOfClass: 底层源码实现
+ (BOOL)isMemberOfClass:(Class)cls { return self->ISA() == cls; } - (BOOL)isMemberOfClass:(Class)cls { return [self class] == cls; } + (BOOL)isKindOfClass:(Class)cls { for (Class tcls = self->ISA(); tcls; tcls = tcls->getSuperclass()) { if (tcls == cls) return YES; } return NO; } - (BOOL)isKindOfClass:(Class)cls { for (Class tcls = [self class]; tcls; tcls = tcls->getSuperclass()) { if (tcls == cls) return YES; } return NO; }
通过源码可知:
- isMemberOfClass:
如果是类对象比较的是类对象的isa(也就是元类对象)与传入类对象进行比较;如果是实例对象比较的是实例对象的类对象与传入的类对象进行比较;
- isKindOfClass:
如果是类对象比较的是通过当前类对象isa(也就是元类对象)与传入的类对象进行比较,并依据当前类对象逐层向上查找是否相等;如果是实例对象比较的实例对象的类对象与传入的类对象进行比较,并依据当前类对象逐层向上查找是否相等;
具体结果分析:1. person的类对象和NSObject类对象比较,不相等;然后Person的父类NSObject的类对象与NSObject类对象比较,则相等;
[person isKindOfClass:[NSObject class]]; //打印结果: 1
2. person的类对象和Person类对象比较,则相等;
[person isKindOfClass:[Person class]]; //打印结果: 1
3. person的类对象与NSObject的类对象比较,不相等;
[person isMemberOfClass:[NSObject class]]; //打印结果: 0
4. person的类对象和Person类对象比较,则相等;
[person isMemberOfClass:[Person class]]; //打印结果: 1
5. NSObject的元类对象与NSObject类对象比较,不相等;由于NSObject的元类对象最终又指向了NSObject类对象再次与NSObject类对象比较,则相等;参考前文
[[NSObject class] isKindOfClass:[NSObject class]]; //打印结果: 1
6. NSObject的元类对象与NSObject类对象比较,则不相等;
[[NSObject class] isMemberOfClass:[NSObject class]]; //打印结果: 0
7. Person的元类对象与Person类对象比较,则不相等;继续向上查找,最终也不相等;
[[Person class] isKindOfClass:[Person class]]; //打印结果: 0
8. Person的元类对象与Person类对象比较,则不相等
[[Person class] isMemberOfClass:[Person class]]; //打印结果: 0
9. Person的元类对象NSObject类对象比较,不相等;然后NSObject的元类对象与NSObject类对象比较,不相等;然后NSObject类对象与NSObject类对象比较,故相等;
[[Person class] isKindOfClass:[NSObject class]]; //打印结果: 1
本文部分内容来可能来源于网络,发布的内容如果侵犯了您的权益,请联系我们尽快删除!