Reflektierende Programmierung

Im Informatik, Reflektierende Programmierung oder Betrachtung ist die Fähigkeit von a Prozess prüfen, Introspekt, und modifizieren Sie seine eigene Struktur und sein eigenes Verhalten.[1]

Historischer Hintergrund

Die frühesten Computer wurden in ihrer Heimat programmiert Assemblersprachen, die von Natur aus reflektierend waren, da diese ursprünglichen Architekturen durch Definition von Anweisungen als Daten und Verwendung programmiert werden konnten selbstmodifizierender Code. Als der Großteil der Programmierung auf höhere Ebene bewegte kompilierte Sprachen wie zum Beispiel Algol, Cobol, Forran, Pascal, und CDiese reflektierende Fähigkeit verschwand weitgehend, bis neue Programmiersprachen mit eingebauten Reflexionen in ihren Typsystemen erschienen.

Brian Cantwell SmithDie Dissertation von 1982 führte den Begriff der rechnerischen Reflexion in prozeduraler Verfahren ein Programmiersprachen und der Begriff der Meta-kreisförmiger Dolmetscher Als Komponente von 3-lisp.[2][3]

Verwendet

Reflection hilft Programmierern, generische Software -Bibliotheken zu erstellen, Daten anzuzeigen, verschiedene Datenformate zu verarbeiten, auszuführen Serialisierung oder Deserialisierung von Daten für Kommunikation oder Bündelung und Entbündelung von Daten für Container oder Kommunikationsausbrüche.

Effektiver Einsatz der Reflexion erfordert fast immer einen Plan: ein Design -Framework, Codierungsbeschreibung, Objektbibliothek, eine Karte einer Datenbank oder Entitätsbeziehungen.

Reflexion macht eine Sprache, die für netzwerkorientierte Code besser geeignet ist. Zum Beispiel hilft es Sprachen wie hilft Java Um in Netzwerken gut zu arbeiten, indem Bibliotheken für die Serialisierung, Bündelung und unterschiedliche Datenformate aktiviert werden. Sprachen ohne Reflexion wie z. C sind erforderlich, um Hilfskompiler für Aufgaben wie zu verwenden Abstract Syntax Notation Code für Serialisierung und Bündelung erzeugen.

Reflexion kann zur Beobachtung und Änderung der Programmausführung bei verwendet werden Laufzeit. Eine reflexionsorientierte Programmkomponente kann die Ausführung eines Codehegels überwachen und sich nach einem gewünschten Ziel dieses Gehäuses ändern. Dies wird in der Regel durch dynamisches Zuweisen von Programmcode zur Laufzeit erreicht.

Im Objekt orientierte Programmierung Sprachen wie Java, Reflexion erlaubt Inspektion von Klassen, Schnittstellen, Feldern und Methoden zur Laufzeit, ohne die Namen der Schnittstellen, Felder, Methoden bei zu kennen Zeit kompilieren. Es erlaubt auch Instanziierung von neuen Objekten und Aufruf von Methoden.

Reflexion wird oft als Teil von verwendet Softwaretest, wie für die Laufzeitherstellung/Instanziierung von Scheinobjekte.

Reflexion ist auch eine Schlüsselstrategie für Metaprogrammierung.

In einigen objektorientierten Programmiersprachen wie z. C# und Java, Reflexion kann verwendet werden, um umzugehen Zugänglichkeit der Mitglieder Regeln. Für C#-Properties kann dies erreicht werden, indem direkt auf das (normalerweise unsichtbare) Hintergrund einer nicht öffentlichen Eigenschaft geschrieben wird. Es ist auch möglich, nicht öffentliche Methoden von Klassen und Typen zu finden und sie manuell aufzurufen. Dies eignet .NETZ's Assemblies und Javas Archive.

Implementierung

Eine Sprachunterstützungsreflexion bietet eine Reihe von Funktionen zur Laufzeit, die ansonsten in einer Sprache auf niedrigerer Ebene schwierig zu erreichen sind. Einige dieser Funktionen sind die Fähigkeiten, um:

  • Entdecken und ändern Quellcode Konstruktionen (wie Codeblöcke, Klassen, Methoden, Protokolle usw.) als erstklassige Objekte bei Laufzeit.
  • Konvertieren a Saite Übereinstimmung mit dem symbolischen Namen einer Klasse oder Funktion in einen Verweis auf diese Klasse oder Funktion oder Aufruf von dieser Klasse.
  • Bewerten Sie eine Zeichenfolge, als wäre es zur Laufzeit eine Quellcode-Anweisung.
  • Erstelle eine neue Dolmetscher für die Sprache der Sprache Bytecode eine neue Bedeutung oder einen neuen Zweck für ein Programmierkonstrukt zu geben.

Diese Funktionen können auf unterschiedliche Weise implementiert werden. Im MUHEN, Reflexion ist ein natürlicher Bestandteil der alltäglichen Programmierrede. Wenn Verben (Methoden) aufgerufen werden, verschiedene Variablen wie z. Verb (der Name des aufgerufenen Verbs) und Dies (Das Objekt, auf das das Verb aufgerufen wird) wird besiedelt, um den Kontext des Anrufs zu geben. Die Sicherheit wird in der Regel durch programmatisch auf den Anruferstapel verwaltet: seitdem Anrufer() ist eine Liste der Methoden, mit denen das aktuelle Verb schließlich aufgerufen wurde, und Tests durchführen Anrufer() [0] (der vom ursprünglichen Benutzer aufgerufene Befehl ermöglicht es dem Verb, sich vor nicht autorisierter Verwendung zu schützen.

Kompilierte Sprachen beruhen auf ihr Laufzeitsystem, um Informationen über den Quellcode bereitzustellen. Ein zusammengestellt Ziel c Ausführbare Datei zeichnet beispielsweise die Namen aller Methoden in einem Block der ausführbaren Datei auf und stellt eine Tabelle bereit, um diese den zugrunde liegenden Methoden (oder Selektoren für diese Methoden) zu entsprechen, die in das Programm zusammengestellt wurden. In einer kompilierten Sprache, die die Laufzeitschaffung von Funktionen unterstützt, wie z. Common LispDie Laufzeitumgebung muss einen Compiler oder einen Dolmetscher enthalten.

Reflexion kann für Sprachen ohne integrierte Reflexion mit a implementiert werden Programmumwandlung System zur Definition automatisierter Quellcode-Änderungen.

Sicherheitsüberlegungen

Reflexion kann es einem Benutzer ermöglichen, unerwartet zu erstellen Steuerfluss Wege durch eine Anwendung, die möglicherweise Sicherheitsmaßnahmen umgeht. Dies kann von Angreifern ausgenutzt werden.[4] Historisch Schwachstellen In Java, die durch eine unsichere Reflexion verursacht wurden, ermöglichte Code aus potenziell nicht vertrauenswürdigen Fernmaschinen aus dem Java aus Sandkasten Sicherheitsmechanismus. Eine große Studie mit 120 Java -Schwachstellen im Jahr 2013 kam zu dem Schluss, dass eine unsichere Reflexion die häufigste Schwachstelle in Java ist, aber nicht die am meisten ausgebeutete.[5]

Beispiele

Die folgenden Codeausschnitte erstellen eine Beispiel foo von Klasse Foo und rufe seine auf Methode PrintHello. Für jeden ProgrammierspracheEs werden normale und reflexionsbasierte Anrufsequenzen angezeigt.

C#

Das Folgende ist ein Beispiel in C#:

// ohne Reflexion Foo Foo = Neu Foo(); Foo.Printhello(); // mit Reflexion Objekt Foo = Aktivator.CreateInstance("complete.classPath.and.foo"); MethodInfo Methode = Foo.Gettyp().GetMethod("Printhello"); Methode.Aufrufen(Foo, Null); 

Delphi / Objekt Pascal

Dies Delphi/Objekt Pascal Beispiel nimmt an, dass a Tfoo Die Klasse wurde in einer Einheit namens deklariert Einheit 1:

Verwendet Rtti, Einheit 1; Verfahren Withoutreflection; var  Foo: Tfoo; Start  Foo : = Tfoo.Schaffen;  Versuchen  Foo.Hallo;  endlich  Foo.Frei;  Ende; Ende; Verfahren WithReflexion; var  Rtticontext: Trtticontext;  Rttitype: TrttiinStancetype;  Foo: Tobjekt; Start  Rttitype : = Rtticontext.FINDTYPE('Unit1.tfoo') wie TrttiinStancetype;  Foo : = Rttitype.GetMethod('Schaffen').Aufrufen(Rttitype.Metaklasstyp, []).ASObject;  Versuchen  Rttitype.GetMethod('Hallo').Aufrufen(Foo, []);  endlich  Foo.Frei;  Ende; Ende; 

EC

Das Folgende ist ein Beispiel in EC:

// ohne Reflexion Foo Foo { }; Foo.hallo(); // mit Reflexion Klasse Fooklasse = ESYSTEM_FINDCLASS(__thismodul, "Foo"); Beispiel Foo = Einstance_New(Fooklasse); Methode m = ecklass_findmethod(Fooklasse, "hallo", Fooklasse.Modul); ((Leere (*) ()) (Leere *)m.Funktion) (Foo); 

gehen

Das Folgende ist ein Beispiel in gehen:

importieren "reflektieren" // ohne Reflexion f : = Foo{} f.Hallo() // mit Reflexion ft : = reflektieren.Art der(Foo{}) fv : = reflektieren.Neu(ft) m : = fv.MethodByName("Hallo") wenn m.Ist gültig() {  m.Anruf(Null) } 

Java

Das Folgende ist ein Beispiel in Java:

importieren Java.lang.reflect.Method; // ohne Reflexion Foo Foo = Neu Foo(); Foo.hallo(); // mit Reflexion Versuchen {  Objekt Foo = Foo.Klasse.GetDeclaredConstructor().Newinstance();  Methode m = Foo.GetClass().GetDeclaredMethod("hallo", Neu Klasse[0]);  m.aufrufen(Foo); } Fang (ReflexionoperationException ignoriert) {} 

JavaScript

Das Folgende ist ein Beispiel in JavaScript:

// ohne Reflexion Const Foo = Neu Foo() Foo.hallo() // mit Reflexion Const Foo = Reflektieren.konstruieren(Foo) Const hallo = Reflektieren.erhalten(Foo, 'hallo') Reflektieren.anwenden(hallo, Foo, []) // mit eval bewerten('New Foo (). Hallo ()' ') 

Julia

Das Folgende ist ein Beispiel in Julia (Programmiersprache):

Julia> Struktur Punkt  x::Int  y  Ende # Inspektion mit Reflexion Julia> Feldnamen(Punkt) (: x ,: y) Julia> Fieldypes(Punkt) (INT64, Anywein) Julia> p = Punkt(3,4) # Zugang mit Reflexion Julia> Getfield(p, :x) 3 

Ziel c

Das Folgende ist ein Beispiel in Ziel c, was entweder die impliziert OpenStep oder Foundation Kit Framework wird verwendet:

// Foo -Klasse. @Schnittstelle Foo: NSOBJECT - (Leere)hallo; @Ende // "Hallo" ohne Reflexion an eine Foo -Instanz senden. Foo *obj = [[Foo Alloc] drin]; [obj hallo]; // Senden Sie "Hallo" mit Reflexion an eine Foo -Instanz. Ich würde obj = [[NSCASSFROMStrING(@"Foo") Alloc] drin]; [obj Performelector: @Wähler(hallo)]; 

Perl

Das Folgende ist ein Beispiel in Perl:

# Ohne Reflexion mein $ foo = Foo->Neu; $ foo->hallo; # oder Foo->Neu->hallo; # Mit Reflexion mein $ Klasse = "Foo" mein $ Constructor = "Neu"; mein $ method = "hallo"; mein $ f = $ Klasse->$ Constructor; $ f->$ method; # oder $ Klasse->$ Constructor->$ method; # mit eval bewerten "NEU FOO-> Hallo;"; 

Php

Das Folgende ist ein Beispiel in Php:

// ohne Reflexion $ foo = Neu Foo(); $ foo->hallo(); // mit Reflexion mit Reflexionen API $ reflektor = Neu Reflexionsklasse("Foo"); $ foo = $ reflektor->Newinstance(); $ Hallo = $ reflektor->GetMethod('hallo'); $ Hallo->aufrufen($ foo); 

Python

Das Folgende ist ein Beispiel in Python:

# Ohne Reflexion obj = Foo() obj.hallo() # Mit Reflexion obj = Global() ["Foo"] () Getattr(obj, "hallo") ()) # Mit eval bewerten("Foo (). Hallo ()") 

R

Das Folgende ist ein Beispiel in R:

# Ohne Reflexion gibt angenommen, foo () gibt ein S3-Objekt zurück, das Methode "Hallo" hat obj <- Foo() hallo(obj) # Mit Reflexion Klassenname <- "Foo" generic_having_foo_method <- "hallo" obj <- do.call(Klassenname, aufführen()) do.call(generic_having_foo_method, eine Liste(obj)) 

Rubin

Das Folgende ist ein Beispiel in Rubin:

# Ohne Reflexion obj = Foo.Neu obj.hallo # Mit Reflexion Klassenname = "Foo" method_name = :hallo obj = Objekt.const_get(Klassenname).Neu obj.senden method_name # Mit eval bewerten "Foo.new.hello" 

Xojo

Das Folgende ist ein Beispiel für die Verwendung Xojo:

'Ohne Reflexion Schwach Fooinstance Wie Neu Foo Fooinstance.Printhello 'Mit Reflexion Schwach klasseninfo Wie Selbstbeobachtung.Typinfo = Gettypeinfo(Foo) Schwach Konstrukteure() Wie Selbstbeobachtung.Konstruktorinfo = klasseninfo.GetConstructors Schwach Fooinstance Wie Foo = Konstrukteure(0).Aufrufen Schwach Methoden() Wie Selbstbeobachtung.MethodInfo = klasseninfo.GetMethods Zum Jeder m Wie Selbstbeobachtung.MethodInfo Im Methoden  Wenn m.Name = "Printhello" Dann  m.Aufrufen(Fooinstance)  Ende Wenn Nächste 

Siehe auch

Verweise

Zitate

  1. ^ Ein Tutorial zur Verhaltensreflexion und deren Umsetzung durch Jacques Malenfant et al. (PDF), unbekannt, archiviert von das Original (PDF) am 21. August 2017, abgerufen 23. Juni 2019
  2. ^ Brian Cantwell Smith, Verfahrensreflexion in Programmiersprachen, Abteilung für Elektrotechnik und Informatik, Massachusetts Institute of Technology, PhD Dissertation, 1982.
  3. ^ Brian C. Smith. Reflexion und Semantik in einer prozeduralen Sprache Archiviert 2015-12-13 bei der Wayback -Maschine. Technischer Bericht MIT-LCS-TR-272, Massachusetts Institute of Technology, Cambridge, Massachusetts, Januar 1982.
  4. ^ Barros, Paulo; Nur, René; Millstein, Suzanne; Reben, Paul; Dietl, Werner; D'Amorim, Marcelo; Ernst, Michael D. (August 2015). Statische Analyse des impliziten Kontrollfluss (PDF) (Bericht). Universität von Washington. UW-CSE-15-08-01. Abgerufen 7. Oktober, 2021.
  5. ^ Eauvidoum, IEU; Festplattenrauschen (5. Oktober 2021). "Zwanzig Jahre der Flucht vor der Java -Sandbox". Phrack. Vol. 10, nein. 46. Abgerufen 7. Oktober, 2021.{{}}: CS1 Wartung: Verwendet Autorenparameter (Link)

Quellen

Weitere Lektüre

  • Ira R. Forman und Nate Forman, Java -Reflexion in Aktion (2005), ISBN1-932394-18-4
  • Ira R. Forman und Scott Danforth, Metaklasse zur Arbeit bringen (1999), ISBN0-201-43305-2

Externe Links