目标c是KindOfClass的误区吗?

时间:2010-01-11 22:58:56

标签: objective-c instanceof

我有以下对象结构:

动物,狗和猫。正如您所期望的那样,Dog和Cat是从Animal继承的。

我有一个农场班:

 @implementation AnimalFarm

-(Animal*) createAnimal:(AnimalType)type{

  switch (type) {

    case CAT:
      return [Cat new];

    case DOG:
      return [Dog new];

    default:
      return [Animal new];
  }

}

@end

我尝试进行单元测试:

  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!");

课程的实施:

@interface Cat : Animal {

}


@end

@implementation Cat

  -(NSString*) say{
    return @"miau";
}

@end

狗的实施类似。

但是KindOfClass或isMemberOfClass都没有像我预期的那样工作....

我错过了什么吗?


当我使用IF代替切换时,一切顺利......但有什么区别?

有效的createAnimal的实现:

-(Animal *) createAnimal:(AnimalType)type {

  if (type == DOG) {
    return [Dog new]; 
  } else if (type == CAT) {
    return [Cat new]; 
  } else {
    return [Animal new];
  }

3 个答案:

答案 0 :(得分:45)

如果实例的类完全相同,

isMemberOfClass:将仅返回YES,但如果实例的类相同,则isKindOfClass:将返回YES,或者给定的班级。

例如,这将输出No!

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

但这会输出Yes!

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

这是因为NSMutableArray是NSArray的,但它不是NSArray类的成员(否则它不会是NSMutableArray)。

在整个Foundation和Cocoa中,有许多“类集群”。您可以在Apple's developer web site的文档中阅读更多相关信息。由于类集群的性质,如果您创建了NSString对象,则可能无法通过isMemberOfClass:[NSString class]测试。

如果isKindOfClass:isMemberOfClass:都没有返回正确的值,请查看实际对象所在的类

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

如果这些返回的内容不是预期的,那么您的场类就会出现问题。

答案 1 :(得分:3)

你的问题出在其他地方。

我创建了您的AnimalDogCat类,以及您上面传达的四个案例。作为参考,这是我的代码:http://pastie.org/774468

输出:

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

编辑:

我认为你的AnimalFarm对象有可能是错误的来源,但我只是尝试以这种方式创建动物对象并获得相同的结果(代码: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

编辑#2:

根据你的观察结果if ... else if语句有效但switch语句没有,我修改了上面发布的代码以使用switch语句....并且它工作得很好。所以我的评论/问题代表:在你的if / switch语句中,你使用了这些常量DOGCAT。那些定义在哪里?

答案 2 :(得分:-9)

你错过了休息时间,这就是你的开关无法正常工作的原因。它看起来应该是这样的。

switch (type) {

 case CAT:
   return [Cat new];
 break;
 case DOG:
   return [Dog new];
 break;
 default:
   return [Animal new];
 break;
}