objective-c - solucion - hierbas para eyaculación precoz
¿Objective-C tiene reflejo? (4)
Estoy investigando sobre Objective-C, y me gustaría saber si tiene el concepto de reflexión. Ninguno de los documentos que he encontrado hasta ahora describe la reflexión.
Hay una gran cantidad de métodos que pueden acceder a varias propiedades de una clase y, presumiblemente, "echar un vistazo" y "meter" en algunos objetos internos. Nunca he jugado con ellos, y una pequeña lectura que he hecho sugiere que están lejos de ser perfectos, pero parecen ofrecer cierta capacidad de "reflexión", similar al concepto de Java.
Hay funciones de tiempo de ejecución descritas en Runtime Reference que permite no solo consultar las características de una clase o instancia, sino también agregar un método o incluso crear una nueva clase en tiempo de ejecución. Digo que este es un tipo muy dinámico de reflexión, que generalmente no estaba disponible para los lenguajes basados en C. Los envoltorios de Mike Ash son un contenedor de Objective-C alrededor de eso. De nuevo, ¡puede incluso agregar métodos! La clase base de Cocoa, NSObject
, también proporciona envoltorios para muchas de las funciones de tiempo de ejecución, consulte la referencia del protocolo NSObject
. Por ejemplo
[foo respondsToSelector:@selector(bar:)];
if([foo isKindOfClass:[NSString class]]){ ... }
hace lo que dicen los nombres de los métodos. Incluso puede agregar un método sobre la marcha. Por ejemplo,
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
@interface Foo:NSObject
{
}
@end
@implementation Foo
-(void)sayHi
{
NSLog(@"Hi! from %@",NSStringFromSelector(_cmd));
}
+(BOOL)resolveInstanceMethod:(SEL)sel
{
Method method=class_getInstanceMethod(self,@selector(sayHi));
class_addMethod(self,sel,method_getImplementation(method),method_getTypeEncoding(method));
return YES;
}
@end
int main(){
NSAutoreleasePool*pool=[[NSAutoreleasePool alloc] init];
Foo* foo=[[Foo alloc] init];
[foo aeiou];
[foo bark];
[foo mew];
[pool drain];
return 0;
}
Esto produce la salida
Hi! from aeiou
Hi! from bark
Hi! from mew
Lo que hace es lo siguiente:
-
SEL
es la variable que representa el mensaje enviado (o llamada a un método, en la otra terminología). - Objective-C runtime calls
resolveInstanceMethod:
de una clase si un mensaje enviado a una instancia no se implementa en la clase - Entonces, en este caso, solo copio una implementación de un método predefinido llamado
sayHi
a la implementación de ese método. - Desde el método, puede usar
_cmd
para ver cuál fue el selector utilizado al llamar al método. Entonces, incluso desde una única implementación desayHi
, podemos obtener resultados diferentes.
Parte de la implementación estándar de Cocoa (Key-Value-Coding, Key-Value-Observing y Core Data en particular) usa el tiempo de ejecución para modificar dinámicamente la clase.
Sí, Objective-C tiene reflejo (y clases abstractas). Si esa reflexión se ajusta a sus necesidades o no es una pregunta diferente.
La reflexión en Objective-C es sorprendentemente flexible para un lenguaje derivado de C. Puede preguntar a una clase qué métodos implementa o puede modificar y / o agregar métodos a las clases existentes. Incluso puede crear nuevas clases sobre la marcha o cambiar la clase de cualquier instancia en cualquier momento.
Un programa típico de Objective-C no hace ninguna de estas cosas (al menos no directamente) excepto por ocasionalmente llamar a respondsToSelector:
o conformsToProtocol:
Si bien Objective-C es un lenguaje completamente dinámico, reflexivo y orientado a objetos, eso no significa que dichos patrones se fomenten o se usen de manera típica.
Puede encontrar interesantes mis respuestas a estas preguntas:
En Objective C, ¿cómo averiguar el tipo de devolución de un método a través de la reflexión?
¿Objective-C tiene una biblioteca estándar?
Características de tiempo de ejecución de Smalltalk ausentes en Objective-C?
Y, por supuesto, el tiempo de ejecución está muy bien documentado . Como es el lenguaje . O podrías leer la fuente .
Supongo que no sé qué aspecto de la reflexión estás buscando. ¿Estás buscando cómo determinar qué clase es una variable dada? Si es así, mira esto: Objective-C class -> string like: [NSArray className] -> @ "NSArray"
// Get a object''s class name
if ([NSStringFromClass([foo class]) compare:@"NSSomeObject"] == NSOrderedSame) {...}
// Does an object have a method
[foo respondsTo:@selector(method:)]
¿Estás buscando algo más que esto?