阅读 129

isMemberOfClass和isKindOfClass

class和superClass

classsuperclassNSObject.mm源码中的实现

+ (Class)class {
    return self;
}

- (Class)class {
    return object_getClass(self);
}

+ (Class)superclass {
    return self->superclass;
}

- (Class)superclass {
    return [self class]->superclass;
}
复制代码

从源码中可以分析出:

  • 实例对象的- (Class)class方法,返回的是类对象
  • 类对象的+ (Class)class方法,返回的是类对象本身
  • 实例对象的- (Class)superclass方法,返回的是父类的类对象
  • 类对象的+ (Class)superclass方法,返回的也是父类的类对象

举例

创建两个类:PersonStudent

@interface Person : NSObject

@end

//------------------------------

@interface Student : Person

@end

Student *stu = [[Student alloc] init];

// ===== class =====
// 结果都打印1   因为[stu class]和[Student class]返回的都是Student类对象
NSLog(@"%d", [stu class] == [Student class]);
NSLog(@"%d", [Student class] == [Student class]);

// 结果打印0     因为Student类对象 不等于 Person类对象
NSLog(@"%d", [Student class] == [Person class]);

// ===== superClass =====
// 结果打印0    stu的superClass返回的是父类Person类对象,所以不相等
NSLog(@"%d", [stu superclass] == [Student class]);
// 结果打印1    
NSLog(@"%d", [stu superclass] == [Person class]);

// 结果打印0   Student的superClass返回的是父类Person的类对象,所以不相等
NSLog(@"%d", [Student superclass] == [Student class]);
// 结果打印1
NSLog(@"%d", [Student superclass] == [Person class]);
复制代码

isMemberOfClass和isKindOfClass

NSObject.mm源码如下:

+ (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->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;
}
复制代码

从源码中可以分析出:

  • 实例对象的 - (BOOL)isMemberOfClass:(Class)cls 方法,比较的是当前类的类对象和传入类的类对象是否相等
  • 实例对象的 - (BOOL)isKindOfClass:(Class)cls 方法,比较的是当前类的类对象传入类的类对象是否相等,如果不相等,则往上比较父类类对象传入类对象是否相等
  • 类对象的 + (BOOL)isMemberOfClass:(Class)cls 方法,比较的是当前类的元类传入的类对象是否相等 (元类也是类对象的一种)
  • 类对象的 + (BOOL)isKindOfClass:(Class)cls 方法,比较的是当前类的元类传入的类对象是否相等,如果不相等,则网上比较父类的元类对象传入类对象是否相等

所以本质上,实例方法比较的是类对象是否相等;类方法比较的是元类对象是否相等

举例

// ===== 实例方法 =====

// 结果都为1 [Student class] 方法返回的是Student类对象,所以比较相等
NSLog(@"%d", [stu isMemberOfClass:[Student class]]);        
NSLog(@"%d", [stu isKindOfClass:[Student class]]);          

// 结果为0   这里isMemberOfClass比较的是Student类对象和Person类对象,所以不相等
NSLog(@"%d", [stu isMemberOfClass:[Person class]]);         
// 结果为1   isKindOfClass先比较Student类对象和Person类对象是否相等,
// 不相等,所以找到Student的父类类对象Person,比较相等所以结果为1
NSLog(@"%d", [stu isKindOfClass:[Person class]]);           

// ===== 类方法 =====

// 结果都为0   因为类方法比较的是元类对象,[Student class] 返回的是类对象,所以不相等
NSLog(@"%d", [Student isMemberOfClass:[Student class]]);
NSLog(@"%d", [Student isKindOfClass:[Student class]]);

// 结果都为1   因为object_getClass([Student class])方法返回的是Student的元类对象
NSLog(@"%d", [Student isMemberOfClass:object_getClass([Student class])]);
NSLog(@"%d", [Student isKindOfClass:object_getClass([Student class])]);
// 结果也是1  当前类的元类对象不等于传入类对象时,会往上比较父类的元类对象是否等于当前元类对象
NSLog(@"%d", [Student isKindOfClass:object_getClass([Person class])]);
// 特别注意,以下结果也是1,因为NSObject的元类对象的父类是NSObject类对象
NSLog(@"%d", [Student isKindOfClass:[NSObject class]]);
复制代码

**说明: 以下两种方式本质上是一样的 **

因为Student调用类方法,使用的是类对象调用类方法 

[Student class]返回的是类对象本身,所以本身也是类对象调用类方法

  •  [Student isKindOfClass:[Student class]];
  •  [[Student class] isKindOfClass:[Student class]];

注意:

NSObject的元类对象的父类是NSObject类对象,所以任意继承自NSObject类的类对象调用

[xxx isKindOfClass:[NSObject class]],结果都为1

文章分类
iOS
文章标签