对方法的探索,全篇分六个章节
三、面试题分析
前言
本章节分析下面两类方法的区别
self.class 和 super.class
isKindOfClass 和 isMemberOfClass
[toc]
3.1 self.class 和 super.class
-
测试代码
- (instancetype)init { if (self = [super init]) { NSLog(@"self.class : %@",self.class); NSLog(@"super.class : %@",super.class); } return self; }
-
输出
self.class : SRStudent super.class : SRStudent
-
分析
-
class
方法有两个隐藏参数,一个self
,一个是SEL
; -
super.class
调用的方法是objc_msgSendSuper
,消息接受者还是self
; -
super.class
只是表示在方法查找的时候跳过从自己的方法列表中查找,直接从父类方法列表中开始查找;
-
3.2 isKindOfClass 和 isMemberOfClass
-
方法源码
+ (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) { if (tcls == cls) return YES; } return NO; }
-
isKindOfClass总结
1.先取比较对象的 cls
* 如果是实例对象,则取的是 class,实例对象->类对象
* 如果是类对象,则取的是元类,类对象->元类
2.然后 遍历
cls
的superclass
* 如果匹配到相同的,直接返回 YES
* 如果一直没匹配到相同,返回 NO -
isMemberOfClass总结
- 选取比较对象的 cls,直接跟被比较的对象比较
- 相对于
isKindOfClass
,不会去遍历superclass
进行匹配。 - 如果是实例对象,则取的是 class,
实例对象->类对象
,用类对象比较 - 如果是类对象,则取的是元类,
类对象->元类
,用元类对象比较
3.2.1 类方法调用例子
-
+ (BOOL)isKindOfClass:(Class)cls
方法分析-
方法调用格式
[A isKindOfClass:B]
- A-tcls 初始值:A的元类
- A-tcls 偏移值:A的元类的父类
- B-cls:用来做比较的类
A的元类/A的元类的父类/包括NSObject类 只要有 和B相同的即为真
-
方法调用例子
- BOOL re1 = [(id)[NSObject class] isKindOfClass:[NSObject class]]; // 1
-
* A : NSObject元类/NSObject类
* B : NSObject类
A和B有一个相同的NSObject类,所以返回真
2. BOOL re3 = [(id)[LGPerson class] isKindOfClass:[LGPerson class]]; // 0
* A : LGPerson元类/NSObject元类/NSObject类
* B : LGPerson类
A和B没有一个相同的类,所以返回假
-
+ (BOOL)isMemberOfClass:(Class)cls
方法分析-
方法调用格式
[A isMemberOfClass:B]
- A-self:A的元类
- B-cls:用来做比较的类
-
方法调用例子
- BOOL re2 = [(id)[NSObject class] isMemberOfClass:[NSObject class]]; // 0
-
* A : NSObject元类
* B : NSObject类
不相同,所以返回假
2. BOOL re4 = [(id)[LGPerson class] isMemberOfClass:[LGPerson class]]; // 0
* A : LGPerson元类
* B : LGPerson类
不相同,所以返回假
3.2.2 对象方法调用例子
-
- (BOOL)isKindOfClass:(Class)cls
方法分析-
方法调用格式
[A isKindOfClass:B]
- A-tcls 初始值:A的类
- A-tcls 偏移值:A的类的父类
- B-cls:用来做比较的类
-
方法调用例子
-
BOOL re5 = [(id)[NSObject alloc] isKindOfClass:[NSObject class]]; // 1
- A : NSObject类
- B : NSObject类
-
BOOL re7 = [(id)[LGPerson alloc] isKindOfClass:[LGPerson class]]; // 1
- A : LGPerson类/NSObject类
- B : LGPerson类
-
-
-
- (BOOL)isMemberOfClass:(Class)cls
方法分析-
方法调用格式
[A isMemberOfClass:B]
- A-self:A的类
- B-cls:用来做比较的类
-
方法调用例子
-
BOOL re6 = [(id)[NSObject alloc] isMemberOfClass:[NSObject class]]; // 1
- A : NSObject类
- B : NSObject类
-
BOOL re8 = [(id)[LGPerson alloc] isMemberOfClass:[LGPerson class]]; // 1
-
-
* A : LGPerson类
* B : LGPerson类
网友评论