Article directory
1. Interview questions: isKindClass and isMemberOfClass
NSLog(@"%d",[[NSObject class] isKindOfClass:[NSObject class]]); //The final comparison here is whether the metaClass of the NSObject class object is the same as its class object, and the result is different when combined with the class diagram. NSLog(@"%d",[[NSObject class] isMemberOfClass:[NSObject class]]); NSLog(@"---------"); //Firstly, the left LYMPerson class object's metaClass is compared with the right LYMPerson class object. If the left LYMPerson class object's metaClass's parent class is further compared, the results are different according to the class diagram. NSLog(@"%d",[[LYMPerson class] isKindOfClass:[LYMPerson class]]); // The metaClass of LYMPerson class object is different from that of LYMPerson class object combined with class diagram. NSLog(@"%d",[[LYMPerson class] isMemberOfClass:[LYMPerson class]]); NSLog(@"---------"); // The metaClass of LYMPerson class object is compared with NSObject, while the difference continues to compare the parent class of LYMPerson `class object'metaClass, because the final parent class of LYMPerson is NSObject, so the result is the same with class diagram. NSLog(@"%d",[[LYMPerson class] isKindOfClass:[NSObject class]]); // Compared with NSObject, metaClass of LYMPerson class object has different results combined with class diagram. NSLog(@"%d",[[LYMPerson class] isMemberOfClass:[NSObject class]]);
If you want to study the above problems, you have to look at the following picture:
Let's start with the implementation of this part in the open source code of the NOSBject part of objc:
+ (BOOL)isMemberOfClass:(Class)cls { return object_getClass((id)self) == cls; } - (BOOL)isMemberOfClass:(Class)cls { return [self class] == cls; } + (BOOL)isKindOfClass:(Class)cls { for (Class tcls = object_getClass((id)self); tcls; tcls = tcls->superclass) { if (tcls == cls) return YES; } return NO; } - (BOOL)isKindOfClass:(Class)cls { for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {//This is where we keep looking for the original class. if (tcls == cls) return YES; } return NO; } + (BOOL)isSubclassOfClass:(Class)cls { for (Class tcls = self; tcls; tcls = tcls->superclass) { if (tcls == cls) return YES; } return NO; }
From the source code, we can see that:
- In the instance method, isMemberOfClass only compares whether the class object of the instance method is the same as that of the incoming class; isKindOfClass is to judge whether the class object of the instance method is compared with the incoming class; if it is not the same, it compares with the parent class of the class object of the instance method, layer by layer.
- In the class method, isMemberOfClass only takes the metaClass of the class object to judge whether it is equal to the incoming class object; isKindOfClass compares the metaClass of the class object with the incoming class, and if it is different, compares it with the parent class of the original class object of the class object, layer by layer.
In summary. If all output is required to be correct, the above code is modified to read as follows:
#import <objc/runtime.h> int main(int argc, const char * argv[]) { @autoreleasepool { NSLog(@"%d",[NSObject isKindOfClass:[NSObject class]]); NSLog(@"%d",[NSObject isMemberOfClass:object_getClass([NSObject class])]); NSLog(@"---------"); NSLog(@"%d",[LYMPerson isKindOfClass:object_getClass([LYMPerson class])]); NSLog(@"%d",[LYMPerson isMemberOfClass:object_getClass([LYMPerson class])]); NSLog(@"---------"); NSLog(@"%d",[LYMPerson isKindOfClass:[NSObject class]]); NSLog(@"%d",[[LYMPerson superclass] isMemberOfClass:object_getClass([NSObject class])]); } return 0; }
The modified output is as follows:
The analysis of each output of the above interview questions is explained in the comments section above each line of code.