Nella programmazione per computer , la riflessione è la capacità di un programma di esaminare, e possibilmente modificare, le proprie strutture interne di alto livello durante l' esecuzione .
Chiamiamo riflessività fa per un linguaggio di programmazione per consentire la scrittura di tali programmi. Si dice che un tale linguaggio di programmazione sia riflessivo .
Ci sono due tecniche utilizzate dai sistemi riflettenti:
L' introspezione viene utilizzata per eseguire misurazioni delle prestazioni, ispezionare moduli o eseguire il debug di un programma. È implementato in linguaggi come Smalltalk o Java che forniscono strumenti per conoscere la classe di un oggetto, i suoi attributi , i suoi metodi , ecc. L'introspezione non esiste in linguaggi come C o Pascal (ma esiste in Delphi dalla versione 2010).
L' intercessione consente a un programma di cambiare automaticamente in base alle esigenze e all'ambiente. Questa proprietà appare in linguaggi come Smalltalk , Groovy o Python , ma non esiste in linguaggi come C.
La riflessione, l'introspezione e l'intercessione sono casi speciali di metaprogrammazione .
Accanto ai concetti di introspezione e intercessione, esistono due tipi di riflessione: riflessione strutturale (che riguarda principalmente il codice del programma) e riflessione comportamentale (che riguarda principalmente l'ambiente del programma).
La riflessione strutturale consiste nel reificare il codice di un programma e tutti i tipi astratti disponibili attraverso il programma. Nel primo caso, la reificazione del codice di un programma permette di gestire questo programma durante l'esecuzione. È così possibile mantenere un programma anche quando sta eseguendo delle attività. Nel secondo caso, la reificazione dei tipi astratti consente al programma di esaminare e modificare la struttura dei tipi complessi. È così possibile, ad esempio, sviluppare algoritmi di serializzazione generici .
La riflessione comportamentale (o comportamento di riflessione) si riferisce più in particolare all'implementazione del programma e all'ambiente del programma. Con questo tipo di riflessione un programma può "sapere" come viene interpretato e può quindi modificare il modo in cui viene eseguito, intervenendo sulle strutture dati del valutatore del programma e sul valutatore stesso. Il programma, infatti, può ottenere informazioni sulla sua attuazione o addirittura auto-riorganizzarsi per adattarsi al meglio a un “ambiente”.
Nella programmazione orientata agli oggetti , l'architettura riflessiva è implementata dal concetto di metaoggetti . Questi rappresentano elementi di programmi orientati agli oggetti come classi, messaggi e funzioni generiche. La manipolazione di questi metaoggetti avviene tramite un protocollo di metaoggetti che permette di decidere il comportamento del linguaggio. CLOS è il primo linguaggio ad aver implementato un protocollo meta-oggetto.
Le seguenti lingue sono riflessive:
Nei linguaggi interpretati o compilati al volo prima dell'esecuzione ( Lisp per esempio), non c'è differenza tra l'interpretazione del codice e la riflessione poiché è il codice sorgente che si evolve e non solo il codice risultante della compilazione.
Il seguente esempio è scritto in Java :
// Sans utiliser la réflexion Foo foo = new Foo(); foo.hello(); // En utilisant la réflexion Class<?> cl = Class.forName("package.name.Foo"); // Instanciation de l'objet dont la méthode est à appeler Object instance = cl.newInstance(); // Invocation de la méthode via réflexion Method method = cl.getClass().getDeclaredMethod("hello", new Class<?>[0]); method.invoke(instance);L'esempio seguente è scritto in C# :
// Sans utiliser la réflexion Foo foo = new Foo(); foo.hello(); // En utilisant la réflexion Type type = typeof(Foo); // Instanciation de l'objet dont la méthode est à appeler // Il existe deux façons d'instancier un objet via la réflexion : // 1, soit : ConstructorInfo constructor = type.GetConstructor(Type.EmptyTypes); object instance = constructor.Invoke(new object[]{}); // 2, soit : instance = Activator.CreateInstance(type); // Invocation de la méthode via réflexion MethodInfo method = type.GetMethod("hello"); method.Invoke(instance, new object[]{});I due pezzi di codice creano un'istanza della classe Foo e chiamano il loro metodo hello .
Nel primo programma, i nomi delle classi e dei metodi sono codificati, non è possibile utilizzare il nome di un'altra classe. Nel secondo programma, invece, i nomi delle classi e dei metodi possono variare in fase di esecuzione.