这是我写的一个小测试程序:
#importint main(int argc, char **argv) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSArray *arr = [NSArray array]; printf("Arr isMemberOfClass NSArray: %d\n", [arr isMemberOfClass:[NSArray class]]); printf("Arr isKindOfClass NSArray: %d\n", [arr isKindOfClass:[NSArray class]]); [pool release]; return 0; }
它的输出:
$ ./ismemberof Arr isMemberOfClass NSArray: 0 Arr isKindOfClass NSArray: 1
-isMemberOfClass:
任何Foundation类中的方法有用吗?我理解这可能会为我子类的类提供所需的结果,但对于基础类 - 我发现我的arr变量的结果是非直观的.之所以会发生这种情况,是因为NSArray不是一个具体的类,而是一个抽象类,并且在引擎盖下NSArray实际上是NSCFArray的具体实例?
你通常想要isKindOfClass:
,而不是isMemberOfClass:
.不同的是,isKindOfClass:
将返回YES
如果接收机是有问题的类的子类的一个成员,而isMemberOfClass:
将返回NO
在相同的情况下.
正如格雷厄姆·李指出的那样,NSArray
是一个阶级集群.这意味着每个NSArray
实例实际上都是某个子类的实例 - 因此您的发现.仅对isKindOfClass:
类集群的类成员测试有用.
也就是说,您通常应该使用respondsToSelector:
而不是类成员测试.一个例子是objectEnumerator
,它也是由(NSSet
和NSDictionary
两个也是类集群)实现的.一个例外是plist序列化:集合不是属性列表,因此allObjects
在尝试从中生成plist数据之前,您需要发送到您的集合以获取数组.
当您在自己的类中实现-isEqual:方法时,-isMemberOfClass:非常有用.如果您有这样的课程:
@interface Person : NSObject { NSString *name; NSUInteger age; } @property(copy) NSString *name; @property(assign) NSUInteger age; @end
并且如果两个Person对象具有相同的名称和年龄,则需要将它们视为相同,您必须实现-isEqual:,以及来自NSObject:protocol的-hash方法:
- (BOOL)isEqual:(id)obj { return [obj isMemberOfClass:[self class]] && [obj name] == self.name && [obj age] == self.age; } - (NSUInteger)hash { return [self.name hash] + age; }
PS:为什么使用[obj isMemberOfClass:[self class]]
而不是简单[obj class] == [self class]
?它在上面的代码中并不重要,但是当你处理使用NSProxy的更复杂的代码时它变得很重要.isMemberOfClass:方法将询问代理所代表的对象,如果它是该类的成员,这可能是您想要的.