一. super作用
Person类
#import <Foundation/Foundation.h>
@interface Person : NSObject
@end
#import "Person.h"
@implementation Person
@end
Student类
#import "Person.h"
@interface Student : Person
@end
#import "Student.h"
#import <objc/runtime.h>
@implementation Student
- (instancetype)init
{
if (self = [super init]) {
NSLog(@"[self class] = %@", [self class]); // Student
NSLog(@"[self superclass] = %@", [self superclass]); // Person
// objc_msgSendSuper({self, [Person class]}, @selector(class));
NSLog(@"[super class] = %@", [super class]); // Student
NSLog(@"[super superclass] = %@", [super superclass]); // Person
}
return self;
}
@end
将OC代码转成C/C++代码可以看到[super class]
等于objc_msgSendSuper({self, [Person class]}, @selector(class));
结合上述打印结果可以有如下结论:
-
[super message]
即objc_msgSendSuper(...)
的底层实现
a) 消息接收者仍然是子类对象
b) 从父类开始查找方法的实现
因此可以知道[super message]
的消息接收者(调用者)还是self,只不过是从父类的方法列表开始查找方法而已。
二. isKindOfClass、isMemberOfClass
以下几个log的结果是什么?
NSLog(@"%d", [[NSObject class] isKindOfClass:[NSObject class]]);
NSLog(@"%d", [[NSObject class] isMemberOfClass:[NSObject class]]);
NSLog(@"%d", [[Person class] isKindOfClass:[Person class]]);
NSLog(@"%d", [[Person class] isMemberOfClass:[Person class]]);
//上边等同于下边
NSLog(@"%d", [NSObject isKindOfClass:[NSObject class]]); // 1
NSLog(@"%d", [NSObject isMemberOfClass:[NSObject class]]); // 0
NSLog(@"%d", [Person isKindOfClass:[Person class]]); // 0
NSLog(@"%d", [Person isMemberOfClass:[Person class]]); // 0
猛一看这几个结果可能会有点蒙,需要分析isKindOfClass、isMemberOfClass
的具体含义才可以弄明白以上结果。
通过objc源码可以查看到以上两个方法的具体实现。分别有实例方法和类方法。
- (BOOL)isMemberOfClass:(Class)cls {
return [self class] == cls;
}
- (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {
if (tcls == cls) return YES;
}
return NO;
}
+ (BOOL)isMemberOfClass:(Class)cls {
return object_getClass((id)self) == cls;
}
+ (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = object_getClass((id)self); tcls; tcls = tcls->superclass) {
if (tcls == cls) return YES;
}
return NO;
}
a) - (BOOL)isMemberOfClass:(Class)cls
直接拿到实例的类对象和传入的cls
比较是否相等。
b) - (BOOL)isKindOfClass:(Class)cls
使用传入的cls
和实例的类对象或者父类比较(父类仍是类对象)。
c) + (BOOL)isMemberOfClass:(Class)cls
使用元类对象和传入的cls
比较是否相等。
d) + (BOOL)isKindOfClass:(Class)cls
使用传入的cls
和元类对象或者父类比较(父类仍是元类对象)。
通过上边对每个方法的具体的介绍可以做具体分析了,首先第一个:
-
[[NSObject class] isKindOfClass:[NSObject class]]
就是拿到NSObject
这个类对象的元类对象和[NSObject class]
比较,左边是NSObject
元类对象,右边是NSObject
类对象肯定不同,这时候继续循环比较,左边通过superclass
找到NSObject
这个元类对象的父类就是NSObject
类对象,这个时候左右都是NSObject
的类对象所以相同,返回YES。 -
[[NSObject class] isMemberOfClass:[NSObject class]]
就是拿到NSObject
这个类对象的元类对象和[NSObject class]
比较,左边是NSObject
元类对象,右边是NSObject
类对象肯定不同,返回NO。 -
[[Person class] isKindOfClass:[Person class]]
通过循环遍历左边Person
元类对象的的父类分别为NSObject
元类对象、NSObject
类对象,右边为Person
类对象,所以都不相同,返回NO。 -
[[Person class] isMemberOfClass:[Person class]]
拿到Person
类对象的元类对象和[Person class]
比较,左边为Person
元类对象,右边为Person
类对象,所以不相同,返回NO。
网友评论