isKindOfClass和isMemberOfClass的區(qū)別

想要深入立即isKindOfClassisMemberOfClass的區(qū)別,那就離不開下面這個(gè)圖

image.png

isa 走位鏈(兩條)

  • teacher的isa走位鏈:teacher(子類對象) --> CJLTeacher (子類)--> CJLTeacher(子元類) --> NSObject(根元類) --> NSObject(跟根元類,即自己)

  • person的isa走位圖:person(父類對象) --> CJLPerson (父類)--> CJLPerson(父元類) --> NSObject(根元類) --> NSObject(跟根元類,即自己)

superclass走位鏈(兩條)

  • 類的繼承關(guān)系鏈:CJLTeacher(子類) --> CJLPerson(父類) --> NSObject(根類)--> nil

  • 元類的繼承關(guān)系鏈:CJLTeacher(子元類) --> CJLPerson(父元類) --> NSObject(根元類)--> NSObject(根類)--> nil

示例分享

//LGPerson 繼承自 NSObject
BOOL re1 = [(id)[NSObject class] isKindOfClass:[NSObject class]];        
BOOL re2 = [(id)[LGPerson class] isKindOfClass:[LGPerson class]];    
BOOL re3 = [(id)[NSObject class] isMemberOfClass:[NSObject class]];         
BOOL re4 = [(id)[LGPerson class] isMemberOfClass:[LGPerson class]];     
NSLog(@" re1 :%hhd\n re2 :%hhd\n re3 :%hhd\n re4 :%hhd\n",re1,re2,re3,re4);

BOOL re5 = [(id)[NSObject alloc] isKindOfClass:[NSObject class]];    
BOOL re6 = [(id)[LGPerson alloc] isKindOfClass:[LGPerson class]];          
BOOL re7 = [(id)[NSObject alloc] isMemberOfClass:[NSObject class]];      
BOOL re8 = [(id)[LGPerson alloc] isMemberOfClass:[LGPerson class]];      
NSLog(@" re5 :%hhd\n re6 :%hhd\n re7 :%hhd\n re8 :%hhd\n",re5,re6,re7,re8);
輸出
2020-09-20 21:15:13.975631+0800 KCObjc[2274:69804]  
 re1 :1
 re2 :0
 re3 :0
 re4 :0
2020-09-20 21:15:13.976631+0800 KCObjc[2274:69804]  
 re5 :1
 re6 :1
 re7 :1
 re8 :1

源碼分析

+ (BOOL)isKindOfClass:(Class)cls

+ (BOOL)isKindOfClass:(Class)cls {
    for (Class tcls = self->ISA(); tcls; tcls = tcls->superclass) {
        // 獲取類的元類 vs 傳入類
        // 根元類 vs 傳入類
        // 根類 vs 傳入類
        if (tcls == cls) return YES;
    }
    return NO;
}
  • 1、 BOOL re1 = [(id)[NSObject class] isKindOfClass:[NSObject class]];
  • 傳入的clsNSObject(根類), self 指向 NSObject,進(jìn)入循環(huán)
  • tcls= NSObject meta(根元類),執(zhí)行判斷if (tcls == cls),不相等,進(jìn)入下一個(gè)循環(huán)
  • tcls= NSObject(根類),執(zhí)行判斷if (tcls == cls),相等,return YES
  • 2、 BOOL re2 = [(id)[LGPerson class] isKindOfClass:[LGPerson class]];
  • 傳入的clsLGPerson, self 指向 LGPerson,進(jìn)入循環(huán)
  • tcls= LGPerson meta(元類),執(zhí)行判斷if (tcls == cls),不相等,進(jìn)入下一個(gè)循環(huán)
  • tcls= NSObject meta(根元類),執(zhí)行判斷if (tcls == cls),不相等,進(jìn)入下一個(gè)循環(huán)
  • tcls= NSObject meta(根類),執(zhí)行判斷if (tcls == cls),不相等,進(jìn)入下一個(gè)循環(huán)
  • tcls= nil,結(jié)束循環(huán),

+ (BOOL)isMemberOfClass:(Class)cls

+ (BOOL)isMemberOfClass:(Class)cls {
    //獲取類的元類,與 傳入類對比
    return self->ISA() == cls;
}
  • 3、 BOOL re3 = [(id)[NSObject class] isMemberOfClass:[NSObject class]];
  • 傳入的clsNSObject(根類)self 指向 NSObject,進(jìn)入循環(huán)
  • tcls= NSObject meta(根元類),執(zhí)行判斷if (tcls == cls),不相等
  • 4、 BOOL re4 = [(id)[LGPerson class] isMemberOfClass:[LGPerson class]];
  • 傳入的clsLGPersonself 指向 LGPerson,進(jìn)入循環(huán)
  • tcls= NSObject meta(元類),執(zhí)行判斷if (tcls == cls),不相等

- (BOOL)isKindOfClass:(Class)cls

- (BOOL)isKindOfClass:(Class)cls {
    //獲取對象的類 vs 傳入的類 
    //父類 vs 傳入的類
    //根類 vs 傳入的類
    for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {
        if (tcls == cls) return YES;
    }
    return NO;
}
  • 1、 BOOL re5 = [(id)[NSObject alloc] isKindOfClass:[NSObject class]];
  • 傳入的clsNSObject(根類), self 指向 NSObject實(shí)例對象,進(jìn)入循環(huán),NSObject實(shí)例對象的isa即NSObject(根類)
  • tcls= NSObject(根類),執(zhí)行判斷if (tcls == cls),相等
  • 2、 BOOL re6 = [(id)[LGPerson alloc] isKindOfClass:[LGPerson class]];
  • 傳入的clsLGPerson, self 指向 LGPerson實(shí)例對象,進(jìn)入循環(huán),LGPerson實(shí)例對象的isa即LGPerson
  • tcls= LGPerson,執(zhí)行判斷if (tcls == cls),相等

- (BOOL)isMemberOfClass:(Class)cls

- (BOOL)isMemberOfClass:(Class)cls {
    //獲取對象的類,與 傳入類對比
    return [self class] == cls;
}
  • 1、 BOOL re7 = [(id)[NSObject alloc] isMemberOfClass:[NSObject class]];
  • 傳入的clsNSObject(根類)self 指向 NSObject實(shí)例對象,進(jìn)入循環(huán),NSObject實(shí)例對象的即NSObject(根類)
  • tcls= NSObject(根類),執(zhí)行判斷if (tcls == cls),相等
  • 2、 BOOL re8 = [(id)[LGPerson alloc] isMemberOfClass:[LGPerson class]];
  • 傳入的clsLGPerson, self 指向 LGPerson實(shí)例對象,進(jìn)入循環(huán),LGPerson實(shí)例對象的即LGPerson
  • tcls= LGPerson,執(zhí)行判斷if (tcls == cls),相等

總結(jié)

isKindOfClass

  • 類方法:元類的繼承鏈對比
    • 元類(isa) --> 根元類(父類) --> 根類(父類) --> nil(父類)
  • 實(shí)例方法:對象的類 --> 父類 --> 根類 --> nil傳入類的對比

isMemberOfClass

  • 類方法: 類的元類傳入類 對比
  • 實(shí)例方法:對象的父類傳入類 對比
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容