19

我有以下对象结构:

动物、狗和猫。正如您所料,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

狗的实现是类似的。

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

我错过了什么吗?


当我使用 IF 而不是 switch 时,一切都很顺利......但有什么区别?

有效的 createAnimal 的实现:

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

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

3 回答 3

46

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 开发者网站上的文档中阅读更多相关信息。由于类集群的性质,如果您创建了一个NSString对象,它可能无法通过isMemberOfClass:[NSString class]测试。

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

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

如果这些返回的不是他们应该返回的任何东西,那么你的农场课程就有问题。

于 2010-01-11T23:31:26.070 回答
3

你的问题在别处。

我创建了你的Animal,DogCat类,你上面的四个案例都通过了。作为参考,这是我的代码: 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. 那些定义在哪里?

于 2010-01-12T02:46:26.947 回答
-10

You are missing breaks, that's why your switch isn't working. It should look like this.

switch (type) {

 case CAT:
   return [Cat new];
 break;
 case DOG:
   return [Dog new];
 break;
 default:
   return [Animal new];
 break;
}
于 2011-08-29T20:31:35.487 回答