Цель c является KindOfClass недоразумение? - PullRequest
17 голосов
/ 12 января 2010

У меня следующая структура объектов:

Животное, Собака и Кошка. Как и следовало ожидать, собаки и кошки наследуются от животных.

А у меня класс фермы:

 @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 вместо переключателя, тогда все идет хорошо ... но в чем разница?

Реализация createAnimal, которая работает:

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

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

Ответы [ 3 ]

45 голосов
/ 12 января 2010

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

Если они возвращают что-то кроме того, что они должны, значит, есть проблема с вашим классом фермы.

3 голосов
/ 12 января 2010

Ваша проблема кроется в другом месте.

Я создал ваши классы Animal, Dog и Cat, а также четыре случая, которые вы рассмотрели выше.Для справки вот мой код: 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 операторов, вы используете эти константы DOG и CAT. Где они определены?

0 голосов
/ 30 августа 2011

Вы пропускаете перерывы, поэтому ваш переключатель не работает. Это должно выглядеть так.

switch (type) {

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