En ciencias de la computación , la programación reflexiva o la reflexión es la capacidad de un proceso para examinar, introspectar y modificar su propia estructura y comportamiento. [1]
Antecedentes históricos
Las primeras computadoras se programaron en sus lenguajes ensambladores nativos , que eran intrínsecamente reflectantes, ya que estas arquitecturas originales podían programarse definiendo instrucciones como datos y utilizando código auto modificable . A medida que la programación se trasladó a lenguajes compilados de nivel superior como Algol , Cobol y Fortran (pero también Pascal y C y muchos otros lenguajes), esta capacidad de reflexión desapareció en gran medida hasta que aparecieron los lenguajes de programación con reflexión incorporada en sus sistemas de tipos. [ cita requerida ]
La tesis doctoral de Brian Cantwell Smith de 1982 [2] [3] introdujo la noción de reflexión computacional en lenguajes de programación procedimental y la noción del intérprete meta-circular como un componente de 3-Lisp .
Usos
Reflection ayuda a los programadores a crear bibliotecas de software genéricas para mostrar datos, procesar diferentes formatos de datos, realizar la serialización o deserialización de datos para la comunicación, o agrupar y desagregar datos para contenedores o ráfagas de comunicación.
El uso efectivo de la reflexión casi siempre requiere un plan: un marco de diseño, descripción de codificación, biblioteca de objetos, un mapa de una base de datos o relaciones entre entidades.
La reflexión hace que un lenguaje sea más adecuado para el código orientado a la red. Por ejemplo, ayuda a lenguajes como Java a funcionar bien en redes al habilitar bibliotecas para serialización, agrupación y formatos de datos variables. Los lenguajes sin reflexión (por ejemplo, C ) tienen que utilizar compiladores auxiliares, por ejemplo, para la notación de sintaxis abstracta , para producir código para serialización y agrupación.
La reflexión se puede utilizar para observar y modificar la ejecución del programa en tiempo de ejecución. Un componente de programa orientado a la reflexión puede monitorear la ejecución de un recinto de código y puede modificarse a sí mismo de acuerdo con un objetivo deseado relacionado con ese recinto. Por lo general, esto se logra asignando dinámicamente el código del programa en tiempo de ejecución.
En lenguajes de programación orientados a objetos como Java , la reflexión permite la inspección de clases, interfaces, campos y métodos en tiempo de ejecución sin conocer los nombres de las interfaces, campos y métodos en tiempo de compilación. También permite la creación de instancias de nuevos objetos y la invocación de métodos.
La reflexión se utiliza a menudo como parte de las pruebas de software , como para la creación / creación de instancias de objetos simulados en tiempo de ejecución .
La reflexión también es una estrategia clave para la metaprogramación .
En algunos lenguajes de programación orientados a objetos, como C # y Java , la reflexión se puede utilizar para eludir las reglas de accesibilidad de los miembros . Para las propiedades de C #, esto se puede lograr escribiendo directamente en el campo de respaldo (generalmente invisible) de una propiedad no pública. También es posible encontrar métodos no públicos de clases y tipos e invocarlos manualmente. Esto funciona tanto para archivos internos del proyecto como para bibliotecas externas (.Net-assembly y Java-archive).
Implementación
Una reflexión de soporte de lenguaje proporciona una serie de funciones disponibles en tiempo de ejecución que, de otro modo, serían difíciles de lograr en un lenguaje de nivel inferior. Algunas de estas características son las capacidades para:
- Descubra y modifique las construcciones de código fuente (como bloques de código, clases , métodos, protocolos, etc.) como objetos de primera clase en tiempo de ejecución.
- Convierta una cadena que coincida con el nombre simbólico de una clase o función en una referencia o invocación de esa clase o función.
- Evalúe una cadena como si fuera una declaración de código fuente en tiempo de ejecución.
- Cree un nuevo intérprete para el código de bytes del lenguaje para darle un nuevo significado o propósito a una construcción de programación.
Estas funciones se pueden implementar de diferentes formas. En MOO , la reflexión forma parte natural del lenguaje de programación cotidiano. Cuando se llaman verbos (métodos), se rellenan varias variables como verbo (el nombre del verbo que se llama) y este (el objeto en el que se llama el verbo) para dar el contexto de la llamada. Por lo general, la seguridad se administra accediendo a la pila de llamadas mediante programación: dado que callers () es una lista de los métodos mediante los cuales se llamó finalmente al verbo actual, realizar pruebas en callers () [0] (el comando invocado por el usuario original) permite la verbo para protegerse contra el uso no autorizado.
Los lenguajes compilados se basan en su sistema de tiempo de ejecución para proporcionar información sobre el código fuente. Un ejecutable Objective-C compilado , por ejemplo, registra los nombres de todos los métodos en un bloque del ejecutable, proporcionando una tabla para corresponderlos con los métodos subyacentes (o selectores de estos métodos) compilados en el programa. En un lenguaje compilado que admita la creación de funciones en tiempo de ejecución, como Common Lisp , el entorno de ejecución debe incluir un compilador o un intérprete.
La reflexión se puede implementar para lenguajes que no tienen funciones de reflexión integradas mediante el uso de un sistema de transformación de programas para definir cambios automatizados en el código fuente.
Ejemplos de
Los siguientes fragmentos de código crean una instancia foo
de clase Foo
e invocan su método PrintHello
. Para cada lenguaje de programación , se muestran secuencias de llamadas normales y basadas en reflexión.
C#
El siguiente es un ejemplo en C # :
// Sin reflejo Foo foo = new Foo (); foo . PrintHello ();// Con objeto de reflexión foo = Activador . CreateInstance ( "complete.classpath.and.Foo" ); MethodInfo método = foo . GetType (). GetMethod ( "PrintHello" ); método . Invocar ( foo , nulo );
Delphi / Object Pascal
Este ejemplo de Delphi / Object Pascal asume que una clase TFoo ha sido declarada en una unidad llamada Unit1 :
utiliza RTTI , Unit1 ;procedimiento WithoutReflection ; var Foo : TFoo ; comenzar Foo : = TFoo . Crear ; prueba Foo . Hola ; finalmente Foo . Libre ; terminar ; terminar ;procedimiento WithReflection ; var RttiContext : TRttiContext ; RttiType : TRttiInstanceType ; Foo : TObject ; comience RttiType : = RttiContext . FindType ( 'Unit1.TFoo' ) como TRttiInstanceType ; Foo : = RttiType . GetMethod ( 'Crear' ) . Invocar ( RttiType . MetaclassType , []) . AsObject ; prueba RttiType . GetMethod ( 'Hola' ) . Invocar ( Foo , []) ; finalmente Foo . Libre ; terminar ; terminar ;
CE
El siguiente es un ejemplo en EC :
// Sin reflejo Foo foo { }; foo . hola ();// Con clase de reflexión fooClass = eSystem_FindClass ( __thisModule , "Foo" ); Instancia foo = eInstance_New ( fooClass ); Método m = eClass_FindMethod ( fooClass , "hola" , módulo fooClass . ); (( void ( * ) ()) ( void * ) m . función ) ( foo );
Ir
El siguiente es un ejemplo en Go :
importar "reflejar"// Sin reflejo f : = Foo {} f . Hola ()// Con reflexión fT : = reflexionar . TypeOf ( Foo {}) fV : = reflejar . Nuevo ( fT )m : = fV . MethodByName ( "Hola" ) si m . IsValid () { m . Llamar ( nulo ) }
Java
El siguiente es un ejemplo en Java :
import java.lang.reflect.Method ;// Sin reflejo Foo foo = new Foo (); foo . hola ();// Con la reflexión intente { Object foo = Foo . clase . newInstance (); Método m = foo . getClass (). getDeclaredMethod ( "hola" , nueva clase > [ 0 ] ); m . invocar ( foo ); } catch ( ReflectiveOperationException ignorada ) {}
JavaScript
El siguiente es un ejemplo en JavaScript :
// Sin reflexión const foo = new Foo () foo . hola ()// Con reflexión const foo = Reflect . construct ( Foo ) const hola = Reflexionar . get ( foo , 'hola' ) Reflexionar . aplicar ( hola , foo , [])// Con eval eval ( 'new Foo (). Hello ()' )
Julia
El siguiente es un ejemplo en Julia (lenguaje de programación) :
julia > struct Point x :: Int y end# Inspección con la reflexión Julia > Nombres de campo ( Point ) ( : x , : Y )julia > fieldtypes ( Point ) ( Int64 , Cualquiera )julia > p = Punto ( 3 , 4 )# Acceso con la reflexión Julia > getField ( p , : x ) 3
C objetivo
El siguiente es un ejemplo en Objective-C , lo que implica que se utiliza el marco OpenStep o Foundation Kit :
// Clase Foo. @interface Foo : NSObject - ( void ) hola ; @final// Envío de "hola" a una instancia de Foo sin reflexión. Foo * obj = [[ Foo alloc ] init ]; [ obj hola ];// Envío de "hola" a una instancia de Foo con reflejo. id obj = [[ NSClassFromString ( @ "Foo" ) alloc ] init ]; [ obj performSelector : @selector ( hola )];
Perl
El siguiente es un ejemplo en Perl :
# Sin reflexión my $ foo = Foo -> nuevo ; $ foo -> hola ;# o Foo -> nuevo -> hola ;# Con reflexión my $ class = "Foo" my $ constructor = "new" ; my $ método = "hola" ;my $ f = $ clase -> $ constructor ; $ f -> $ método ;# o $ clase -> $ constructor -> $ método ;# con eval eval "nuevo Foo-> hola;" ;
PHP
El siguiente es un ejemplo en PHP :
// Sin reflejo $ foo = new Foo (); $ foo -> hola ();// Con reflexión, usando Reflections API $ reflector = new ReflectionClass ( 'Foo' ); $ foo = $ reflector -> newInstance (); $ hola = $ reflector -> getMethod ( 'hola' ); $ hola -> invocar ( $ foo );
Pitón
El siguiente es un ejemplo en Python :
# Sin reflexión obj = Foo () obj . hola ()# Con reflexión obj = globals () [ "Foo" ] () getattr ( obj , "hola" ) ()# Con eval eval ( "Foo (). Hola ()" )
R
El siguiente es un ejemplo en R :
# Sin reflexión, asumiendo que foo () devuelve un objeto de tipo S3 que tiene el método "hola" obj <- foo () hola ( obj )Con la reflexión # the.class <- "foo" the.method <- "hola" obj <- do.call ( the.class , la lista ()) do.call ( the.method , a-lista ( obj ))
Rubí
El siguiente es un ejemplo en Ruby :
# Sin reflejo obj = Foo . nuevo obj . Hola# Con reflexión class_name = "Foo" method_name = : hola obj = Objeto . const_get ( nombre_clase ) . nuevo obj . enviar nombre_método# Con eval eval "Foo.new.hello"
Xojo
El siguiente es un ejemplo usando Xojo :
'Sin reflejo Dim fooInstance como nuevo Foo fooInstance . ImprimirHola'Con reflexión Dim classInfo As Introspection . Typeinfo = GetTypeInfo ( Foo ) Dim constructores () Como introspección . ConstructorInfo = classInfo . GetConstructors Dim fooInstance As Foo = constructors ( 0 ). Invocar métodos Dim () como introspección . MethodInfo = classInfo . GetMethods For Each m As Introspection . MethodInfo En métodos Si m . Name = "PrintHello" Entonces m . Invocar ( fooInstance ) End If Next
Ver también
- Lista de plataformas y lenguajes de programación reflexivos
- Espejo (programación)
- Paradigmas de programación
- Autohospedaje
- Código auto modificable
- Introspección de tipo
- tipo de
Referencias
Citas
- ^ Un tutorial sobre la reflexión conductual y su implementación por Jacques Malenfant et al. (PDF) , desconocido, archivado desde el original (PDF) el 21 de agosto de 2017 , consultado el 23 de junio de 2019
- ^ Brian Cantwell Smith, Reflexión procedimental en lenguajes de programación , Departamento de Ingeniería Eléctrica y Ciencias de la Computación, Instituto de Tecnología de Massachusetts, Tesis doctoral, 1982.
- ^ Brian C. Smith. Reflexión y semántica en un lenguaje procedimental Archivado el 13 de diciembre de 2015 en la Wayback Machine . Informe técnico MIT-LCS-TR-272, Instituto de Tecnología de Massachusetts, Cambridge, Massachusetts, enero de 1982.
Fuentes
- Jonathan M. Sobel y Daniel P. Friedman. Introducción a la programación orientada a la reflexión (1996), Universidad de Indiana .
- Técnica Anti-Reflection usando C # y C ++ / CLI wrapper para prevenir el robo de código
Otras lecturas
- Ira R. Forman y Nate Forman, Reflexión de Java en acción (2005), ISBN 1-932394-18-4
- Ira R. Forman y Scott Danforth, Poniendo a trabajar las metaclases (1999), ISBN 0-201-43305-2
enlaces externos
- Reflexión en programación lógica, funcional y orientada a objetos: un breve estudio comparativo
- Introducción a la programación orientada a la reflexión
- Páginas de Brian Foote sobre Reflexión en Smalltalk
- Tutorial de la API de reflexión de Java de Oracle