Objective c isKindOfClass missunderstanding?

instanceof, objective-c

Solution

`isMemberOfClass:` will only return `YES` if the instance's class is exactly the same, however `isKindOfClass:` will return `YES` if the instance's class is the same, or a subclass of the given class.

For example this will output `No!`:

BOOL result = [[NSMutableArray array] isMemberOfClass:[NSArray class]];
NSLog (@"%@", result? @"Yes!" : @"No!");

But this will output `Yes!`:

BOOL result = [[NSMutableArray array] isKindOfClass:[NSArray class]];
NSLog (@"%@", result? @"Yes!" : @"No!");

This is because an NSMutableArray is a kind of NSArray, but it isn't a member of the NSArray class (otherwise it wouldn't be an NSMutableArray).

Throughout Foundation and Cocoa, there are a number of "class clusters". You can read more about this in the documentation on Apple's developer web site. Due to the nature of class clusters, if you create perhaps an `NSString` object, it may fail the `isMemberOfClass:[NSString class]` test.

If neither `isKindOfClass:` or `isMemberOfClass:` is returning the correct value, see what class the actual object is with

NSLog(@"cat class = %@, dog class = %@", [cat className], [dog className]);

If these are returning anything other than what they are supposed to, then there is a problem with your farm class.

Problem

I have following structure of objects: Animal, Dog and Cat. As You expect Dog and Cat are inherited from Animal. And I've a farm class: ``` @implementation AnimalFarm -(Animal*) createAnimal:(AnimalType)type{ switch (type) { case CAT: return [Cat new]; case DOG: return [Dog new]; default: return [Animal new]; } } @end ``` and I tried to unit test: ``` AnimalFarm *farm = [AnimalFarm new]; Animal *dog = [farm createAnimal:DOG]; Animal *cat = [farm createAnimal:CAT]; STAssertTrue([cat isMemberOfClass:[Cat class]],@"cat is not a cat!"); STAssertTrue([dog isMemberOfClass:[Dog class]],@"Dog is not a dog!"); STAssertTrue([cat isKindOfClass:[Animal class]],@"Cat is not an animal!"); STAssertTrue([dog isKindOfClass:[Animal class]],@"Cat is not an animal!"); ``` Implementation of classes: ``` @interface Cat : Animal { } @end @implementation Cat -(NSString*) say{ return @"miau"; } @end ``` Implementation of dog is similar. but neither isKindOfClass or isMemberOfClass worked as I expected.... Am I missing something? When I use IFs instead of switch then everything goes well ... but what is the difference? Implementation of createAnimal which works: ``` -(Animal *) createAnimal:(AnimalType)type { if (type == DOG) { return [Dog new]; } else if (type == CAT) { return [Cat new]; } else { return [Animal new]; } ```

Original source