【问题标题】:Objective c isKindOfClass missunderstanding?Objective c isKindOfClass 的误解?
【发布时间】:2011-01-03 23:19:29
【问题描述】:

我有以下对象结构:

动物、狗和猫。正如您所期望的,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 都没有按我的预期工作....

我错过了什么吗?


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

有效的 createAnimal 的实现:

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

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

【问题讨论】:

  • 澄清一下:isMemberOfClass:isKindOfClass: 在这些示例中都返回 NO?
  • 编译过程中是否收到任何警告?
  • 我们能看到CATDOG的定义吗?另外,你是什么意思“没有像我预期的那样工作”?断言的结果是什么?
  • 什么不起作用?测试是否失败?如果有,是哪些?
  • 在您发布的代码中没有定义CATDOG 常量。

标签: objective-c instanceof


【解决方案1】:

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]);

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

【讨论】:

  • 日志输出为: cat class= Cat, dog class= Dog 我尝试用 alloc 和 init 更改 new 但结果还是一样。如您所见,我使用 isMemberOfClass 比较正确的类,因此它应该返回 YES 以及 isKindOfClass
【解决方案2】:

您的问题出在其他地方。

我创建了您的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。这些是在哪里定义的?

【讨论】:

  • 好吧,我尝试直接使用 [Cat new] 创建实例,一切正常......所以问题出在农场内部
  • @Vitek - 你如何定义CATDOG
【解决方案3】:

您缺少休息时间,这就是您的开关无法正常工作的原因。它应该是这样的。

switch (type) {

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

【讨论】:

    猜你喜欢
    • 2013-01-29
    • 1970-01-01
    • 1970-01-01
    • 2020-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多