Mechanizm refleksji – w informatyce, proces, dzięki któremu program komputerowy może być modyfikowany w trakcie działania w sposób zależny od własnego kodu oraz od zachowania w trakcie wykonania. Związany z nim paradygmat programowania to programowanie refleksyjne.

Refleksja pozwala zarządzać kodem tak, jakby był danymi. Używa się jej najczęściej do zmieniania standardowego zachowania już zdefiniowanych metod lub funkcji, a także do tworzenia własnych konstrukcji semantycznych modyfikujących język. Z drugiej strony kod wykorzystujący refleksję jest mniej czytelny i nie pozwala na sprawdzenie poprawności składniowej i semantycznej w trakcie kompilacji.

Przykład zastosowania mechanizmu refleksji stanowią języki programowania, w których każdy element kodu źródłowego reprezentowany jest strukturami danych dostępnymi dla programisty. Nazywa się je językami homoikonicznymi, a kod źródłowy ich programów jest w istocie danymi. Od decyzji programisty zależy, które jego fragmenty będą wartościowane, a które traktowane jak wartości stałe niewymagające obliczeń. Proces ten może być wielokierunkowy, np. część kodu źródłowego może zostać potraktowana jak dane, przekształcona, a następnie znów wartościowana – w ten sposób działają tzw. makra składniowe w dialektach języka Lisp.

Mechanizm refleksji jest najczęściej spotykany w językach wysokiego poziomu, szczególnie opartych na maszynie wirtualnej.

Przykłady

edytuj

C#

edytuj

Poniższy przykład demonstruje użycie refleksji w języku C Sharp używając pakietu System.Reflection

//bez refleksji
Foo foo = new Foo();
foo.hello();

//z użyciem refleksji
var type = Type.GetType("namespace.Foo"); // string powinien zawierać namespace naszej klasy
var foo = Activator.CreateInstance(type); // inicjacja obiektu określonego typu
MethodInfo inf = type.GetMethod("hello");
inf.Invoke(foo); // jako drugi parametr metoda Invoke przyjmuje tablicę Object[] są to parametry metody hello.

Objective-C

edytuj

Poniższy przykład demonstruje użycie refleksji w języku Objective-C

// bez refleksji
Foo *foo = [[Foo alloc] init];
[foo hello];
[foo release];

// z refleksją
id foo = [[NSClassFromString(@"Foo") alloc] init];
SEL selector = NSSelectorFromString(@"hello");
[foo performSelector:selector];
[foo release];

Java

edytuj

Poniższy przykład w języku Java wykorzystuje pakiet java.lang.reflect.

 // bez refleksji
 Foo foo = new Foo();
 foo.hello();

 // z refleksją
 Class cl = Class.forName("Foo");
 Method method = cl.getMethod("hello");
 method.invoke(cl.newInstance());

Oba fragmenty tworzą instancję klasy Foo, następnie wywołują metodę hello() tej klasy. Różnica polega na tym, że w pierwszym fragmencie nazwa klasy i metody są częścią kodu źródłowego, podczas gdy w drugim fragmencie możliwe jest przeniesienie ich do zmiennych, których wartość jest ustalana w czasie wykonania kodu.

Mechanizm refleksji pozwala także na zdobywanie informacji o klasach w trakcie wykonania programu. W poniższym przykładzie Klasa Main sprawdza jaki jest typ zwracany przez metody klasy Bar.

public class Bar {
    public String fun(Integer i) {
        return "0" + i + ", zglos sie!";
    }
}

import static java.lang.System.out;
import java.lang.reflect.*;

public class Main {
    public static void main(String[] args) throws Exception {
        String className = "Bar";
        Class c = Class.forName(className);
        Method[] methodArr = c.getDeclaredMethods();
        for (Method m : methodArr) {
	    out.print("Klasa " + className + " ma metode '" + m.getName() + "'");
	    out.println(" ktora zwraca wartosc typu " + m.getReturnType());
        }
    }
}

Ruby

edytuj

Przykład w języku Ruby, który dodaje metodę klasową once, pozwalającą zaznaczyć, że dana funkcja składowa klasy ma być wykonywana tylko raz. Podprogram modyfikuje kod oznaczonych metod w taki sposób, że nadaje im nową nazwę. Pod starą nazwą umieszcza nową metodę, która buforuje wartość zwracaną przez pierwotnie zdefiniowaną funkcję, tym samym pozwalając się jej wykonać tylko raz.

# part of date.rb - date and time library
# Author: Tadayoshi Funaba 1998-2008

class Date
 class << self

    def once(*ids) # :nodoc: -- restricted
      for id in ids
        module_eval <<-"end;"
          alias_method :__#{id.object_id}__, :#{id.to_s}
          private :__#{id.object_id}__
          def #{id.to_s}(*args)
            @__ca__[#{id.object_id}] ||= __#{id.object_id}__(*args)
          end
        end;
      end
    end

    private :once

  end
end

Inny przykład to rozszerzenie możliwości języka o konstrukcję automatycznie kasującą zawartość wskazanych przez programistę buforów, jeśli uruchomione zostaną wyszczególnione metody. Zadaniem metaprogramu jest tu również opakowanie metod, jednak zapamiętywane są identyfikatory ich obiektów a nie identyfikatory obiektów ich symbolicznych nazw. Metaprogram zawarto w przykładowym module BufferAffects, który można pobrać z serwisu GitHub. Domieszkując ten moduł możemy korzystać z dodatkowych metod klasowych pozwalających na stosowanie w kodzie klauzul buffers_reset_method i attr_affects_buffers:

require 'bufferaffects'  # http://gist.github.com/88178

class Main

  # domieszkowanie modułu
  extend BufferAffects

  # metoda opróżniająca wykorzystywany bufor
  buffers_reset_method :reset_path_buffer

  # pola które po zmianie powinny wpływać na
  # zawartość bufora
  attr_affects_buffers :subpart

  # standardowe akcesory pól
  attr_accessor        :subpart, :otherpart

  # metoda opróżniająca bufor
  def reset_path_buffer(name)
    @path = nil
    p "uruchomiono reset dla #{name}"
  end

  # metoda z buforowanym wyjściem
  def path
    @path ||= @subpart.to_s + @otherpart.to_s
  end

end

# tworzenie nowego obiektu
obj = Main.new

# ustawianie jednego z pól
# i wyświetlanie buforowanych wynikow
obj.subpart = 'test'
p obj.path
obj.subpart = '1234'
p obj.path

Linki zewnętrzne

edytuj

📚 Artikel Terkait di Wikipedia

MFC

MFC (skrótowiec od ang. Microsoft Foundation Class Library) – biblioteka Visual C++, której klasy stanowią szkielet aplikacji dla programów pracujących

Typ generyczny

Standard Template Library (STL), opisywana jako zestaw generycznych komponentów C++ przeznaczonych do współpracy w spójny sposób. template <class T> struct Box

Adobe ColdFusion

wsparcia w CFSCRIPT. PHP JavaScript Oficjalna strona Adobe ColdFusion (ang.) ColdFusion User Groups (ang.) Common Function Library Project Zbiór dodatkowych

Pula obiektów (wzorzec projektowy)

zamiast bezpośredniego zarządzania pamięcią działają szybciej. W Base Class Library można znaleźć kilka implementacji tego wzorca. System.Threading.ThreadPool

Python

would be required for an equivalent application written in, say, C++ or Java.. (ang.). About the Python Software Foundation [online], Python.org [dostęp

Object Pascal

przyjrzeć się jak dużym zmianom na przestrzeni wielu lat uległy języki: C++, Java czy nawet C# (najmłodszy z nich). W żadnym z tych przypadków nie dokonano

Funkcja anonimowa

(function(x,y) return x+y)(5,6); // 11 Java obsługuje funkcji anonimowe począwszy od wersji JDK 8. W języku java, funkcje anonimowe nazywane są Wyrażeniami

Lista skrótów i skrótowców używanych w informatyce

Joint Photographic Experts Group JRE – Java Runtime Environment JS – JavaScript JSP – JavaServer Pages JVM – Java Virtual Machine KDE – K Desktop Environment