views:

975

answers:

3

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 isKindOfClass either isMemberOfClass didn't work as I expected....

Am I mising something?

A: 

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.

dreamlax
output of log is: cat class = Cat, dog class = DogI've tried to change new with alloc and init but the result is still the same. As you can see I compare correct classes using isMemberOfClass so It should return YES as well as isKindOfClass
Vitek
+1  A: 

Your problem lies elsewhere.

I created your Animal, Dog, and Cat classes, and the four cases you have above passed. For reference, here is my code: http://pastie.org/774468

It outputs:

2010-01-11 19:45:10.259 EmptyFoundation[83698:a0f] [cat isMemberOfClass:[Cat class]] PASSED
2010-01-11 19:45:10.265 EmptyFoundation[83698:a0f] [dog isMemberOfClass:[Dog class]] PASSED
2010-01-11 19:45:10.265 EmptyFoundation[83698:a0f] [cat isKindOfClass:[Animal class]] PASSED
2010-01-11 19:45:10.273 EmptyFoundation[83698:a0f] [dog isKindOfClass:[Animal class]] PASSED

EDIT:

I suppose there was a slight possibility that your AnimalFarm object was the source of the error, but I just tried creating the animal objects that way and got the same results (code: http://pastie.org/774480):

2010-01-11 19:51:35.144 EmptyFoundation[83741:a0f] [cat isMemberOfClass:[Cat class]] PASSED
2010-01-11 19:51:35.156 EmptyFoundation[83741:a0f] [dog isMemberOfClass:[Dog class]] PASSED
2010-01-11 19:51:35.157 EmptyFoundation[83741:a0f] ![ant isMemberOfClass:[Cat class]] PASSED
2010-01-11 19:51:35.157 EmptyFoundation[83741:a0f] [cat isKindOfClass:[Animal class]] PASSED
2010-01-11 19:51:35.157 EmptyFoundation[83741:a0f] [dog isKindOfClass:[Animal class]] PASSED
2010-01-11 19:51:35.158 EmptyFoundation[83741:a0f] [ant isKindOfClass:[Animal class]] PASSED

EDIT #2:

Based on your observation that an if...else if statement works but the switch statement does not, I modified the code I posted above to use a switch statement.... and it worked just fine. So my comment/question stands: In your if/switch statements, you're using these constants DOG and CAT. Where are those defined?

Dave DeLong
Well, I tried to create instances using [Cat new] directly and everything works....so the problem is inside farm
Vitek
@Vitek - how are you defining `CAT` and `DOG`?
Dave DeLong
what do you mean? My code is shown above...
Vitek
A: 

When I use IFs instead of switch then everything goes well....but What is a 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];
Vitek
this is not an answer. This should be added to your original question.
Dave DeLong