2009-11-27 18 views
9

¿Hay alguna forma de descubrir en tiempo de ejecución qué subclases existen de una clase determinada?Descubre las subclases de una clase determinada en Obj-C

Edit: De las respuestas hasta ahora creo que necesito aclarar un poco más lo que estoy tratando de hacer. Soy consciente de que esta no es una práctica común en Cocoa, y que puede venir con algunas advertencias.

Estoy escribiendo un analizador utilizando el patrón de creación dinámica. (Consulte el libro Cocoa Design Patterns por Buck y Yacktman, capítulo 5.) Básicamente, la instancia del analizador procesa una pila y crea instancias de objetos que saben cómo realizar ciertos cálculos.

Si puedo obtener todas las subclases de la clase MYCommand, puedo, por ejemplo, proporcionar al usuario una lista de comandos disponibles. Además, en el ejemplo del capítulo 5, el analizador sintáctico tiene un diccionario de sustitución para que se puedan usar operadores como +, -, * y /. (Están mapeados al MYAddCommand, etc.). A mí me pareció que esta información pertenecía a la subclase MyCommand, no a la instancia del analizador, ya que de alguna manera se frustra la idea de la creación dinámica.

Respuesta

13

En lugar de intentar registrar automáticamente todas las subclases de MYCommand, por qué no dividir el problema en dos?

En primer lugar, proporcione API para registrar una clase, algo así como +[MYCommand registerClass:].

A continuación, cree el código en MYCommand, lo que significa que las subclases se registrarán automáticamente. Algo así como:

@implementation MYCommand 
+ (void)load 
{ 
    [MYCommand registerClass:self]; 
} 
@end 
+0

Esto parece ser el camino correcto para ir. Especialmente dado que la documentación menciona que se llama al método '+ load' de una clase después de todos sus métodos de superclases' '+ load'. Muchas gracias a las otras personas que proporcionaron respuestas también, sus respuestas también fueron geniales. –

+2

Las subclases de MyCommand no invocarán + cargar en su superclase. + load solo se llama en las clases que lo implementan. –

+0

¡Sorprendido de que alguien me haya tardado tanto en corregirme! En general, estoy de acuerdo con las respuestas aquí que el registro automático es una mala idea y debería manejarse un poco más manualmente. –

19

No directamente, no. Sin embargo, puede obtener una lista de todas las clases registradas con el tiempo de ejecución, así como consultar esas clases para su directo superclase. Tenga en cuenta que esto no le permite encontrar todos los antepasados ​​para la clase en el árbol de herencia, solo la superclase inmediata.

Puede usar objc_getClassList() para obtener la lista de los objetos Class registrados con el tiempo de ejecución. A continuación, puede recorrer ese conjunto y llamar al [NSObject superclass] en esos objetos Class para obtener su objeto de superclase 'Class. Si por alguna razón sus clases no usan NSObject como su clase raíz, puede usar class_getSuperclass() en su lugar.

Debo mencionar también que podría pensar incorrectamente en el diseño de su aplicación si cree que es necesario hacer este tipo de descubrimiento. Lo más probable es que exista otra forma más convencional de hacer lo que se intenta lograr que no implique introspección en el tiempo de ejecución de Objective-C.

+7

Lo diría con más fuerza; si cree que necesita hacer esto en el código de producción, es muy probable que lo esté haciendo mal.La introspección hacia la herencia que mira hacia abajo es extremadamente poco común y es la razón por la cual el tiempo de ejecución no lo soporta directamente. ¿Que estás tratando de hacer? – bbum

+0

@bbum He agregado una descripción de lo que estoy tratando de hacer. ¿Todavía crees que lo estoy haciendo muy mal? Me cuesta pensar en otra forma de hacerlo sin buscar subclases. –

4

Marc y bbum le pegaron al dinero. Esto usualmente no es una buena idea.

Sin embargo, tenemos código en nuestra CocoaHeads wiki que hace esto: http://cocoaheads.byu.edu/wiki/getting-all-subclasses

+1

Otra advertencia; al hacer este tipo de cosas, terminarás haciendo que las clases se + inicialicen en un orden en el que nunca se hayan inicializado. Esto no debería causar problemas, pero a veces se debe a dependencias en las clases del sistema que pueden cambiar en las versiones ... – bbum

+0

La descripción del código vinculado específicamente dice que este enfoque no llama '+ initialize', y aunque no lo tengo Lo he intentado todavía, parece correcto. –

0

No hay código en mi proyecto de ejecución del navegador here que incluye un -subclassNamesForClass: método. Vea los archivos RuntimeReporter.[hm].

+0

Gracias, es una herramienta interesante para agregar a mi cinturón. Aunque aceptaré el enfoque de Mike para este caso en particular. –

+0

Noté que el enlace publicado por @NSResponder está roto. Para aquellos que buscan una forma de recorrer una jerarquía de clases, he escrito un [Logger de Jerarquía de Clase] (https://github.com/sebaven/class-hierarchy-logger) que utiliza un enfoque similar. Puede ser útil si necesita más información sobre cómo iterar la jerarquía de subclase. ¡Espero que ayude! –

3

Otro enfoque fue publicado recientemente por Matt Gallagher en his blog.

Cuestiones relacionadas