2010-01-11 9 views
14

Mam następującą strukturę obiektów:Celem c jest missunderstanding KindOfClass?

Zwierząt, psów i kotów. Jak się spodziewasz, pies i kot są dziedziczone po Zwierzęciu.

i mam klasę rolnicze:

@implementation AnimalFarm 

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

    switch (type) { 

    case CAT: 
     return [Cat new]; 

    case DOG: 
     return [Dog new]; 

    default: 
     return [Animal new]; 
    } 

} 

@end 

i próbowałem testów jednostkowych:

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

Realizacja zajęć:

@interface Cat : Animal { 

} 


@end 

@implementation Cat 

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

@end 

Realizacja pies jest podobny.

ale ani isKindOfClass lub isMemberOfClass działało jak się spodziewałem ....

Am I czegoś brakuje?


Kiedy używam IFs zamiast switcha, wszystko idzie dobrze ... ale jaka jest różnica?

Realizacja createAnimal który działa:

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

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

Aby wyjaśnić: Zarówno 'isMemberOfClass:', jak i 'isKindOfClass:' zwracają NO w tych przykładach? – Chuck

+0

Czy otrzymujesz ostrzeżenia podczas kompilacji? – Chuck

+1

Czy widzimy definicję "CAT" i "DOG"? Co masz na myśli mówiąc "nie działa tak, jak się spodziewałem"? Jakie są wyniki twierdzeń? – Tim

Odpowiedz

39

isMemberOfClass: zwróci jedynie YES jeśli klasa instancji jest dokładnie taka sama, jednak isKindOfClass: powróci YES jeśli klasa instancji jest taka sama, lub podklasą dana klasa.

Na przykład wyjście wola No!:

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

Ale to wyjście wola Yes!:

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

Dzieje się tak dlatego NSMutableArray jest rodzaj z NSArray, ale nie jest to członek klasy NSArray (w przeciwnym razie nie byłaby NSMutableArray).

W całej Fundacji i kakao istnieje wiele "klastrów klasowych". Możesz przeczytać więcej na ten temat w dokumentacji na Apple's developer web site. Ze względu na naturę klastrów klas, jeśli utworzysz obiekt prawdopodobnie NSString, może on nie powieść testu isMemberOfClass:[NSString class].

Jeśli ani isKindOfClass: lub isMemberOfClass: zwraca prawidłową wartość, co klasa rzeczywisty obiekt jest z

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

Jeśli są powrocie coś innego niż to, co oni mają, to nie ma problemu z odbiornikiem klasa gospodarstwa.

+0

wyjście dziennika to: cat class = Cat, dog class = Dog Próbowałem zmienić nowy przy pomocy alloc i init, ale wynik jest taki sam. Jak widać porównuję poprawne klasy przy użyciu isMemberOfClass, więc Powinno to zwrócić TAK, a także jest KindOfClass – Vitek

3

Twój problem leży gdzie indziej.

Utworzone przez Ciebie klasy: Animal, Dog i Cat, a także cztery powyższe przypadki.Dla porównania, tutaj jest mój kod: http://pastie.org/774468

To Wyjścia:

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 

EDIT:

Przypuszczam nastąpił niewielki możliwość, że obiekt AnimalFarm był źródłem błędu, ale po prostu Próbowałem tworzenia obiektów zwierzęcych tamtędy i dostał takie same wyniki (kod: 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 

EDIT # 2:

Na podstawie obserwacji, że instrukcja if ... else if działa, ale instrukcja switch nie, zmodyfikowałem kod, który napisałem powyżej, aby użyć instrukcji switch .... i działało dobrze. Więc mój komentarz/pytanie oznacza: W instrukcjach if/switch używasz tych stałych: DOG i CAT. Gdzie są zdefiniowane?

+0

Cóż, próbowałem utworzyć wystąpienia za pomocą [Cat new] bezpośrednio i wszystko działa .... więc problem jest wewnątrz farmy – Vitek

+0

@ Vitek - jak definiujesz "CAT" i "DOG"? –

+0

co masz na myśli? Mój kod jest pokazany powyżej ... – Vitek

-9

Brakuje przerw, dlatego przełącznik nie działa. To powinno wyglądać tak.

switch (type) { 

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

zwraca już działać jako przerwa – Tim