web-dev-qa-db-ja.com

Objective c isKindOfClassの誤解?

私は次のオブジェクトの構造を持っています:

動物、犬、猫。ご想像のとおり、犬と猫は動物から受け継がれています。

そして私は農場のクラスを持っています:

 @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];
  }
18
Vitek

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の開発者Webサイト のドキュメントを参照してください。クラスクラスターの性質上、おそらくNSStringオブジェクトを作成すると、isMemberOfClass:[NSString class]テストに失敗する可能性があります。

isKindOfClass:isMemberOfClass:も正しい値を返さない場合は、実際のオブジェクトがどのクラスにあるかを確認してください

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

これらが想定以外のものを返している場合は、ファームクラスに問題があります。

45
dreamlax

あなたの問題は他の場所にあります。

AnimalDog、およびCatクラスを作成しましたが、上記の4つのケースに合格しました。参考までに、私のコードは次のとおりです。 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/77448 ):

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を使用しています。それらはどこで定義されていますか?

3
Dave DeLong