2010-01-11 22 views
14

Tengo la siguiente estructura de objetos:Objetivo c isKindOfClass mal entendido?

Animal, perros y gatos. Como espera, Dog y Cat son heredados de Animal.

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 

Aplicación del perro es similar.

pero tampoco isKindOfClass o isMemberOfClass trabajaron como yo esperaba ....

Me estoy perdiendo algo?


Cuando uso IFs en lugar de switch, todo va bien ... pero ¿cuál es la diferencia?

Implementación de createAnimal que trabaja:

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

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

Para aclarar: Both 'isMemberOfClass:' y 'isKindOfClass:' devuelven NO en esos ejemplos? – Chuck

+0

¿Y recibe advertencias durante la compilación? – Chuck

+1

¿Podemos ver la definición de 'CAT' y' DOG'? Además, ¿a qué te refieres con "no funcionó como esperaba"? ¿Cuáles son los resultados de las afirmaciones? – Tim

Respuesta

39

isMemberOfClass: sólo devolverá YES si la clase de la instancia es exactamente el mismo, sin embargo isKindOfClass: regresará YES si la clase de la instancia es la misma, o una subclase de lo dado clase.

Por ejemplo, esta es la salida No!:

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

Pero esta es la salida Yes!:

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

Esto se debe a una NSMutableArray es un tipo de NSArray, pero no es una miembro de la clase NSArray (de lo contrario, no sería un NSMutableArray).

A lo largo de Foundation y Cocoa, hay una serie de "clusters de clase". Puede leer más sobre esto en la documentación en Apple's developer web site. Debido a la naturaleza de los clústeres de clases, si crea quizás un objeto NSString, puede fallar la prueba isMemberOfClass:[NSString class].

Si ninguno isKindOfClass: o isMemberOfClass: devuelve el valor correcto, ver qué clase de objeto real es con

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

Si éstos están regresando otra cosa que lo que se supone que, entonces hay un problema con su clase de granja

+0

La salida del registro es: cat class = Cat, dog class = Dog He intentado cambiar las novedades con alloc e init, pero el resultado sigue siendo el mismo. Como puede ver, comparo las clases correctas usando isMemberOfClass, así debería devolver YES así como isKindOfClass – Vitek

3

Su problema está en otra parte.

Creé su Animal, Dog y Cat clases, y los cuatro casos que ha aprobado anteriormente.Como referencia, aquí está mi código: http://pastie.org/774468

Genera:

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:

supongo que había una ligera posibilidad de que su objeto AnimalFarm fue el origen del error, pero yo sólo intentó crear los objetos de origen animal de esa manera y conseguido 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 sentencia if ... else if funciona pero la instrucción switch no, modifiqué el código que publiqué anteriormente para usar una declaración de cambio .... y funcionó bien. Entonces mi comentario/pregunta permanece: en sus declaraciones if/switch, está usando estas constantes DOG y CAT. ¿Dónde están esos definidos?

+0

. Intenté crear instancias usando [Cat new] directamente y todo funciona ... por lo que el problema está dentro de la granja – Vitek

+0

@ Vitek: ¿cómo defines 'CAT' y' DOG'? –

+0

¿qué quieres decir? Mi código se muestra arriba ... – Vitek

-9

Faltan descansos, por eso su interruptor no funciona. 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; 
} 
+9

vueltas ya actúan como un descanso – Tim