Objective c isKindOfClass missunderstanding?
objective-c instanceof (3)
Tengo la siguiente estructura de objetos:
Animal, Perro y Gato. Como esperas, el perro y el gato son heredados de los animales.
Y tengo una clase de granja:
@implementation AnimalFarm
-(Animal*) createAnimal:(AnimalType)type{
switch (type) {
case CAT:
return [Cat new];
case DOG:
return [Dog new];
default:
return [Animal new];
}
}
@end
y traté de prueba de unidad:
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!");
Implementación de clases:
@interface Cat : Animal {
}
@end
@implementation Cat
-(NSString*) say{
return @"miau";
}
@end
La implementación del perro es similar.
pero ni isKindOfClass ni isMemberOfClass funcionaron como esperaba ...
¿Me estoy perdiendo de algo?
Cuando uso IFs en lugar de cambiar, todo va bien ... pero ¿cuál es la diferencia?
Implementación de createAnimal que funciona:
-(Animal *) createAnimal:(AnimalType)type {
if (type == DOG) {
return [Dog new];
} else if (type == CAT) {
return [Cat new];
} else {
return [Animal new];
}
Te estás perdiendo descansos, es por eso que tu interruptor no está funcionando. Debe tener un aspecto como este.
switch (type) {
case CAT:
return [Cat new];
break;
case DOG:
return [Dog new];
break;
default:
return [Animal new];
break;
}
Tu problema está en otra parte.
Creé tus clases de Animal
, Dog
y Cat
, y los cuatro casos que has superado anteriormente. Para referencia, aquí está mi código: http://pastie.org/774468
Produce:
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
EDITAR:
Supongo que había una pequeña posibilidad de que su objeto AnimalFarm
fuera la fuente del error, pero simplemente intenté crear los objetos animales de esa manera y obtuve los mismos resultados (código: 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
EDITAR # 2:
En base a su observación de que una instrucción if ... else if funciona, pero la instrucción switch no funciona, modifiqué el código que publiqué anteriormente para usar una instrucción switch ... y funcionó bien. Así que mi comentario / pregunta es válida: en sus sentencias if / switch, está utilizando estas constantes DOG
y CAT
. ¿Dónde están los definidos?
isMemberOfClass:
solo devolverá YES
si la clase de la instancia es exactamente la misma, sin embargo isKindOfClass:
devolverá YES
si la clase de la instancia es la misma, o una subclase de la clase dada.
Por ejemplo, esto dará como resultado No!
:
BOOL result = [[NSMutableArray array] isMemberOfClass:[NSArray class]];
NSLog (@"%@", result? @"Yes!" : @"No!");
Pero esto dará como resultado Yes!
:
BOOL result = [[NSMutableArray array] isKindOfClass:[NSArray class]];
NSLog (@"%@", result? @"Yes!" : @"No!");
Esto se debe a que un NSMutableArray es un tipo de NSArray, pero no es un miembro de la clase NSArray (de lo contrario no sería un NSMutableArray).
A lo largo de Foundation y Cocoa, hay una serie de "grupos de clases". Puede leer más sobre esto en la documentación en el sitio web para desarrolladores de Apple . Debido a la naturaleza de los clústeres de clase, si creas quizás un objeto NSString
, puede fallar la prueba isMemberOfClass:[NSString class]
.
Si ni isKindOfClass:
o isMemberOfClass:
está devolviendo el valor correcto, vea con qué clase está el objeto real
NSLog(@"cat class = %@, dog class = %@", [cat className], [dog className]);
Si estos devuelven algo distinto de lo que se supone que deben hacer, entonces hay un problema con su clase de granja.