2012-05-11 17 views
11

¿Hay un equivalente en Objective-C de dynamic_cast de C++?Objective-C dynamic_cast?

Se puede ser falsificada usando esto:

MyClass *safeObject = [object isKindOfClass: [MyClass class]] 
         ? (MyClass *)originalObject : nil; 

Pero esto es una gran cantidad de código para escribir, incluso si yo no necesito para escribir a menudo.

estoy un poco oxidado por lo que esto podría no ser del todo bien, pero creo que el equivalente en C++ sería:

MyClass safeObject = dynamic_cast<MyClass>(orginalObject); 

El contexto aquí es un bloque donde el parámetro se define como un tipo de una clase más genérica, pero en este bloque "sé" que es una subclase específica. Sin embargo, no quiero simplemente lanzarlo a ciegas con (MyClass *)originalObject e ignorar un error teóricamente posible.

Para ser claro, aunque me encantaría un dynamic_cast, estaría encantado con un enfoque alternativo para manejar de forma segura este caso también.

+0

En el peor de los casos, podría escribir una macro para esto. – JustSid

+4

Objective-C está escrito en pato. Honestamente, los moldes "complicados" están remar contra el lenguaje. – zneak

+0

Sí, estoy pensando que probablemente hice la pregunta incorrecta aquí. Cualquier pregunta que * debería haber * preguntado tenía una respuesta de "simplemente use' NSAssert ([object isKindOfClass: [MyClass class]], @ "blahblah") 'porque de todos modos no lo espera." :) –

Respuesta

15

Si usted está dispuesto a usar objetivo -C++, puede escribir esto con bastante facilidad:

template<typename T> inline T* objc_cast(id from) { 
    if ([from isKindOfClass:[T class]]) { 
     return static_cast<T*>(from); 
    } 
    return nil; 
} 

Esto debería comportarse exactamente como dynamic_cast<> a excepción de obj-c objetos.


Si desea seguir con la vainilla Obj-C, usted puede obtener un comportamiento similar con un método de clase en NSObject:

@interface NSObject (Cast) 
+ (instancetype)cast:(id)from; 
@end 

@implementation NSObject (Cast) 
+ (instancetype)cast:(id)from { 
    if ([from isKindOfClass:self]) { 
     return from; 
    } 
    return nil; 
} 
@end 

Esta versión no es tan agradable de usar ya que se debe decir algo como

UIButton *button = [UIButton cast:someView]; 

En ambas versiones el valor resultante es nil si falla el reparto.

+0

Este segundo ejemplo es * exactamente * lo que estaba buscando. Y algo brillantemente simple. Gracias. –

+0

que es un buen uso del operador de tipo de instancia, por lo que el compilador y el autocompletado de Xcode pueden comenzar a usar inmediatamente el tipo convertido – SystematicFrank

3
  1. No creo que exista.
  2. Creo que el espacio para un error es bastante pequeño aquí.
  3. Pero si insistes, ¿funcionará bien una macro?
7

Prueba esta macro:

#define objc_dynamic_cast(obj, cls) \ 
    ([obj isKindOfClass:(Class)objc_getClass(#cls)] ? (cls *)obj : NULL) 

Y también no se olvide de

#include <objc/runtime.h> 

usarlo como:

MyClass *safeObject = objc_dynamic_cast(originalObject, MyClass); 
+0

Espero que no te importe, pero envolví tu macro y agregué el (cls *) para satisfacer una advertencia del compilador. ¡Gran trabajo! Dudé en utilizar una macro aquí debido a la edición de Xcode en el alcance, pero parece funcionar maravillosamente. –

+0

¿Te importaría agregar una línea que muestre cómo usar esta macro (para personas de afuera más verdes). Gracias. – Wienke

+0

Agregué uno. (H2CO3: Si sientes que estoy estropeando tu respuesta, siéntete libre de revertir. ¡Solo estoy tratando de ayudar a los futuros lectores!) –

Cuestiones relacionadas