Gibt es Probleme bei der Verwendung von Reflection?


49

Ich weiß nicht warum, aber ich habe immer das Gefühl, zu "schummeln", wenn ich Reflektion benutze - vielleicht liegt es an dem Performance-Hit, den ich kenne.

Ein Teil von mir sagt, wenn es Teil der Sprache ist, die Sie verwenden, und es das erreichen kann, was Sie versuchen, dann warum nicht. Der andere Teil von mir sagt, es muss einen Weg geben, wie ich das ohne Reflektion machen kann. Ich denke, vielleicht hängt es von der Situation ab.

Auf welche potenziellen Probleme muss ich achten, wenn ich Reflexion verwende, und wie sollte ich mir darüber Gedanken machen? Wie viel Aufwand lohnt es sich, nach einer konventionelleren Lösung zu suchen?


2
Ich denke, es hängt von der Sprache und der Umgebung ab. Einige unterstützen es, ermutigen es sogar. Manchmal habe ich mir bei der Arbeit in Java eine bessere Reflektionsunterstützung gewünscht.
FrustratedWithFormsDesigner

18
Nun, ich denke, es ist nicht so schwer, zwischen "Betrugsreflexion" und einer gültigen Verwendung davon zu unterscheiden: Wenn Sie private Mitglieder untersuchen oder private Methoden aufrufen (um Schnittstellen zu umgehen), ist es sehr wahrscheinlich, dass Sie betrügen. Wenn Sie es verwenden, um mit Typen zu interagieren, über die Sie sonst keine Kenntnisse haben, ist es wahrscheinlich in Ordnung (Datenbindung, Proxies usw.).
Falcon

1
Welche sprache sprichst du Brainfuck hat keine Reflektion und Python ist einfach anders.
Job

1
Ich habe auch nie verstanden, warum es erlaubt ist, durch Reflektion auf private Methoden zuzugreifen. Nach meiner Intuition sollte es verboten sein.
Giorgio

3
Kaum zu glauben, dass eine so schlecht formulierte Frage ohne Bearbeitung 27 positive Stimmen erhielt.
Aaronaught

Antworten:


48

Nein, es ist kein Betrug - es ist eine Möglichkeit, Probleme in einigen Programmiersprachen zu lösen.

Jetzt ist es oft nicht die beste (sauberste, einfachste, am einfachsten zu wartende) Lösung. Wenn es einen besseren Weg gibt, benutze diesen in der Tat. Manchmal ist dies jedoch nicht der Fall. Oder wenn ja, ist es sehr viel komplexer und erfordert viel Code-Duplikation usw., was es unmöglich macht (auf lange Sicht schwierig zu warten).

Zwei Beispiele aus unserem aktuellen Projekt (Java):

  • Einige unserer Testtools verwenden Reflection, um die Konfiguration aus XML-Dateien zu laden. Die zu initialisierende Klasse verfügt über bestimmte Felder, und das Konfigurationsladeprogramm verwendet Reflection, um das benannte XML-Element fieldXmit dem entsprechenden Feld in der Klasse abzugleichen und letzteres zu initialisieren. In einigen Fällen kann ein einfaches GUI-Dialogfeld direkt aus den identifizierten Eigenschaften erstellt werden. Ohne Reflexion würde dies Hunderte von Codezeilen in mehreren Anwendungen erfordern. Durch Reflexion konnten wir schnell und ohne großen Aufwand ein einfaches Tool zusammenstellen und uns auf den wichtigen Teil konzentrieren (Regressionstest unserer Web-App, Analyse von Serverprotokollen usw.), anstatt auf den irrelevanten Teil.
  • Ein Modul unserer alten Web-App war für den Export / Import von Daten aus DB-Tabellen in Excel-Tabellen und zurück gedacht. Es enthielt eine Menge duplizierten Codes, wobei die Duplikate natürlich nicht genau gleich waren. Einige enthielten Bugs usw. Durch Reflektion, Introspektion und Anmerkungen gelang es mir, den größten Teil der Duplikate zu beseitigen und die Menge des Codes zu reduzieren 5K bis unter 2,4K, während der Code robuster und einfacher zu warten oder zu erweitern ist. Jetzt war dieses Modul für uns kein Problem mehr - dank des umsichtigen Einsatzes von Reflektion.

Die Quintessenz ist, wie jedes mächtige Werkzeug, Reflexion kann auch verwendet werden, um sich in den Fuß zu schießen. Wenn Sie lernen, wann und wie Sie es (nicht) verwenden, können Sie elegante und saubere Lösungen für ansonsten schwierige Probleme finden. Wenn Sie es missbrauchen, können Sie ein ansonsten einfaches Problem in ein komplexes und hässliches Chaos verwandeln.


8
+1 Reflexion ist unglaublich nützlich für den Datenimport / -export, wenn Sie aus Konvertierungsgründen Zwischenobjekte haben.
Ed James

2
Es ist auch unglaublich nützlich in datengesteuerten Apps - anstatt einen massiven Stapel von zu verwenden if (propName = n) setN(propValue);, können Sie Ihre (dh) XML-Tags genauso benennen wie Ihre Code-Eigenschaften und eine Schleife über sie ausführen. Diese Methode vereinfacht auch das spätere Hinzufügen von Eigenschaften.
Michael K

Reflexion wird häufig in Fluent-Interfaces wie FluentNHibernate verwendet.
Scott Whitlock

4
@Michael: Bis Sie eine dieser Eigenschaften in der Klasse umbenennen und feststellen, dass Ihr Code explodiert. Wenn Sie die Vergleichbarkeit mit den Dingen, die Ihr Programm erzeugt, nicht aufrechterhalten müssen, ist das in Ordnung, aber ich vermute, das sind nicht die meisten von uns.
Billy ONeal

1
@ Billy, ich wollte dir nicht widersprechen, ich stimme dem zu, was du geschrieben hast. Das Beispiel, das Sie einbringen, ist meiner Meinung nach eher ein Unterfall der allgemeinen Regel "Änderungen an öffentlichen Schnittstellen vermeiden".
Péter Török

37

Es betrügt nicht. Aber es ist normalerweise eine schlechte Idee im Produktionscode, zumindest aus den folgenden Gründen:

  • Sie verlieren die Sicherheit beim Kompilieren - es ist hilfreich, wenn der Compiler überprüft, ob eine Methode zum Kompilierzeitpunkt verfügbar ist. Wenn Sie Reflection verwenden, wird zur Laufzeit ein Fehler angezeigt, der sich auf Endbenutzer auswirken kann, wenn Sie nicht gut genug testen. Selbst wenn Sie den Fehler abfangen, ist das Debuggen schwieriger.
  • Es verursacht Fehler beim Refactoring. Wenn Sie auf ein Mitglied basierend auf seinem Namen zugreifen (z. B. mit einer fest codierten Zeichenfolge), wird dies von den meisten Code-Refactoring-Tools nicht geändert, und es tritt sofort ein Fehler auf, der möglicherweise schwerwiegend ist schwer zu finden.
  • Die Leistung ist langsamer - die Reflexion zur Laufzeit ist langsamer als bei statisch kompilierten Methodenaufrufen / Variablensuchen. Wenn Sie nur gelegentlich reflektieren, ist dies unwichtig. Dies kann jedoch zu einem Leistungsengpass werden, wenn Sie über Reflexion Tausende oder Millionen Mal pro Sekunde Anrufe tätigen. Ich habe einmal eine 10-fache Beschleunigung in einem Clojure-Code erhalten, indem ich einfach alle Überlegungen beseitigt habe, also ja, das ist ein echtes Problem.

Ich würde vorschlagen, die Verwendung der Reflexion auf die folgenden Fälle zu beschränken:

  • Für schnelles Prototyping oder "Wegwerf" -Code, wenn dies die einfachste Lösung ist
  • Für echte Reflection-Anwendungsfälle , z. B. IDE-Tools, mit denen ein Benutzer die Felder / Methoden eines beliebigen Objekts zur Laufzeit untersuchen kann.

In allen anderen Fällen würde ich vorschlagen, einen Ansatz zu finden, der Reflexionen vermeidet. Das Definieren einer Schnittstelle mit den entsprechenden Methoden und das Implementieren dieser Schnittstelle in der Gruppe von Klassen, für die Sie die Methode (n) aufrufen möchten, ist normalerweise ausreichend, um die einfachsten Fälle zu lösen.


3
+1 - Es gibt mehrere Anwendungsfälle für die Reflexion. Aber die meiste Zeit sehe ich, wie Programmierer damit arbeiten und Designs mit schwerwiegenden Fehlern beschriften. Definieren Sie Schnittstellen und versuchen Sie, die Reflektionsabhängigkeit zu beseitigen. Genau wie GOTO hat es seine Verwendung, aber die meisten von ihnen sind nicht gut. (Einige von ihnen sind natürlich gut)
Billy ONeal

3
Beachten Sie, dass die obigen Punkte möglicherweise auf Ihre Lieblingssprache zutreffen oder nicht. Beispielsweise hat die Reflexion in Smalltalk keine Geschwindigkeitseinbußen, und Sie verlieren auch nicht die Sicherheit beim Kompilieren, da die Berechnung vollständig verspätet erfolgt.
Frank Shearar

Reflexion in D hat keinen Nachteil, den Sie erwähnen. Ich würde also argumentieren, dass Sie die Implementierung in einigen Sprachen mehr als die Zurückweisung selbst verantwortlich machen. Ich weiß nicht viel über Smalltalk, aber laut Frank Shearar hat es auch keinen Nachteil.
Deadalnix

2
@deadalinx: Auf welchen Nachteil beziehen Sie sich? In dieser Antwort gibt es mehrere. Das Leistungsproblem ist das einzige, was sprachabhängig ist.
Billy ONeal

1
Ich sollte hinzufügen, dass das zweite Problem - Fehler, die beim Refactoring verursacht wurden - wahrscheinlich das schwerwiegendste ist. Insbesondere das Verlassen auf etwas, das einen bestimmten Namen hat, bricht sofort ab, wenn sich der Name des Dings ändert. Die so verursachten Fehler sind möglicherweise weniger informativ, es sei denn, Sie sind sehr vorsichtig.
Frank Shearar

11

Reflexion ist nur eine andere Form der Metaprogrammierung und genauso gültig wie die typbasierten Parameter, die Sie heutzutage in den meisten Sprachen sehen. Reflexion ist leistungsfähig und allgemein, und Reflexionsprogramme haben eine hohe Wartbarkeitsstufe (natürlich bei korrekter Verwendung) und sind mehr als rein objektorientierte oder prozedurale Programme. Ja, Sie zahlen einen Leistungspreis, aber ich würde gerne ein langsameres Programm wählen, das in vielen oder sogar den meisten Fällen besser gewartet werden kann.


2
+1, das hilft mir zu verstehen, was Reflexion ist . Ich bin ein C ++ - Programmierer, und deshalb habe ich mich nie wirklich überlegt. Das hilft. (Obwohl ich gestehe, dass Reflection aus meiner Sicht ein Versuch ist, einen Sprachmangel zu beheben. Wir C ++ - Leute verwenden dafür Vorlagen. Also könnte man das auch so sagen. :)
greyfade 15.08.11

4
Leistung - In einigen Fällen können Sie die Reflection-API verwenden, um den vollständigen Leistungscode zurückzuschreiben. Zum Beispiel können Sie in .NET IL in die aktuelle App schreiben - daher kann Ihr "Reflection" -Code genauso schnell sein wie jeder andere Code (mit der Ausnahme, dass Sie viel von if / else / whatever entfernen können, wie Sie es bereits getan haben) herausgefunden, die genauen Regeln)
Marc Gravell

@greyfade: In gewisser Weise reflektieren Vorlagen nur die Kompilierungszeit. Die Möglichkeit zur Laufzeit bietet den Vorteil, dass leistungsstarke Funktionen in der Anwendung erstellt werden können, ohne dass eine Neukompilierung erforderlich ist. Sie tauschen Leistung gegen Flexibilität, ein akzeptabler Kompromiss, der (angesichts Ihres C ++ - Hintergrunds) die Zeit übersteigt.
Donal Fellows

Ich verstehe deine Antwort nicht. Sie scheinen zu sagen, dass Programme, die Reflection verwenden, besser gewartet werden können als solche, die Reflection nicht verwenden, als ob Reflection ein überlegenes Programmiermodell ist, das objektorientierte und prozedurale Programme ersetzen sollte, wenn keine Leistung benötigt wird.
DavidS

8

Sicher hängt alles davon ab, was Sie erreichen wollen.

Ich habe zum Beispiel eine Anwendung zur Medienprüfung geschrieben, die mithilfe der Abhängigkeitsinjektion ermittelt, welche Art von Medien (MP3- oder JPEG-Dateien) geprüft werden sollen. Die Shell musste ein Raster mit den relevanten Informationen für jeden Typ anzeigen, wusste jedoch nicht, was angezeigt werden sollte. Dies wird in der Assembly definiert, die diesen Medientyp liest.

Daher musste ich Reflection verwenden, um die Anzahl der anzuzeigenden Spalten sowie ihre Typen und Namen zu ermitteln, damit ich das Raster korrekt einrichten konnte. Es bedeutete auch, dass ich die injizierte Bibliothek aktualisieren (oder eine neue erstellen) konnte, ohne anderen Code oder andere Konfigurationsdateien zu ändern.

Die einzige andere Möglichkeit wäre gewesen, eine Konfigurationsdatei zu haben, die aktualisiert werden müsste, wenn ich den Typ des zu überprüfenden Mediums gewechselt hätte. Dies hätte zu einem weiteren Fehler für die Anwendung geführt.


1
"Sicher hängt alles davon ab, was Sie erreichen wollen." +1
DaveShaw

7

Reflection ist ein großartiges Tool, wenn Sie Bibliotheksautor sind und daher keinen Einfluss auf die eingehenden Daten haben. Eine Kombination aus Reflektion und Metaprogrammierung ermöglicht es Ihrer Bibliothek, nahtlos mit beliebigen Aufrufern zusammenzuarbeiten, ohne dass diese durch Rahmen der Codegenerierung usw. springen müssen.

Ich versuche jedoch, von Überlegungen im Anwendungscode abzuraten . Auf der App-Ebene sollten Sie verschiedene Metaphern verwenden - Schnittstellen, Abstraktion, Kapselung usw.


Solche Bibliotheken sind oft schwer zu benutzen und sollten vermieden werden (zB Spring).
Sridhar Sarnobat

@Sridhar, also haben Sie noch nie eine Serialisierungs-API verwendet? Oder irgendein ORM / Mikro-ORM?
Marc Gravell

Ich habe sie ohne meine eigene Wahl benutzt. Es war demoralisierend, auf Probleme zu stoßen, die ich hätte vermeiden können, wenn mir nicht gesagt worden wäre, was ich tun soll.
Sridhar Sarnobat

7

Reflection eignet sich hervorragend zum Erstellen von Tools für Entwickler.

Dies ermöglicht Ihrer Build-Umgebung, den Code zu überprüfen und möglicherweise die richtigen Tools zum Manipulieren / Initialisieren des Codes zu generieren.

Als allgemeine Programmiertechnik kann sie nützlich sein, ist aber spröder, als sich die meisten Menschen vorstellen.

Eine wirklich entwicklungsbedingte Verwendung für Reflection (IMO) ist, dass das Schreiben einer generischen Streaming-Bibliothek sehr einfach ist (solange sich Ihre Klassenbeschreibung nicht ändert (dann wird es eine sehr spröde Lösung)).


In der Tat ist der Frühling "spröder, als sich die meisten Menschen vorstellen".
Sridhar Sarnobat

5

Die Verwendung von Reflexion ist in OO-Sprachen häufig schädlich, wenn sie nicht mit großem Bewusstsein verwendet wird.

Ich habe die Anzahl der schlechten Fragen, die ich auf StackExchange-Sites gesehen habe, verloren

  1. Die verwendete Sprache ist OO
  2. Der Autor möchte herausfinden, welcher Objekttyp übergeben wurde, und dann eine seiner Methoden aufrufen
  3. Der Autor lehnt es ab, zu akzeptieren, dass Reflexion die falsche Technik ist, und wirft jedem vor, der darauf hinweist, dass er nicht weiß, wie er mir helfen kann.

Hier sind typische Beispiele.

Der meiste Sinn von OO ist das

  1. Sie gruppieren Funktionen, die wissen, wie man eine Struktur / ein Konzept mit dem Ding selbst manipuliert.
  2. An jedem Punkt Ihres Codes sollten Sie genug über den Typ eines Objekts wissen, um zu wissen, über welche relevanten Funktionen es verfügt, und es auffordern, die jeweilige Version dieser Funktionen aufzurufen.
  3. Sie stellen die Richtigkeit des vorherigen Punkts sicher, indem Sie für jede Funktion den richtigen Eingabetyp angeben und jede Funktion nicht mehr wissen (und nicht mehr tun), als relevant ist.

Wenn zu irgendeinem Zeitpunkt in Ihrem Code Punkt 2 für ein Objekt, das Sie übergeben haben, nicht gültig ist, sind einer oder mehrere davon wahr

  1. Die falsche Eingabe wird eingespeist
  2. Ihr Code ist schlecht strukturiert
  3. Sie haben keine Ahnung, was zum Teufel Sie tun.

Schlecht ausgebildete Entwickler verstehen das einfach nicht und glauben, dass sie irgendetwas in ihrem Code weitergeben können und tun, was sie von einer (hartcodierten) Menge von Möglichkeiten wollen. Diese Idioten benutzen viel Reflexion .

Bei OO-Sprachen sollte eine Reflektion nur in Meta-Aktivitäten (Klassenladeprogramme, Abhängigkeitsinjektion usw.) erforderlich sein. In diesen Kontexten ist eine Reflexion erforderlich, da Sie einen allgemeinen Dienst bereitstellen, der Sie bei der Manipulation / Konfiguration von Code unterstützt, von dem Sie aus einem guten und legitimen Grund nichts wissen. In fast jeder anderen Situation, wenn Sie nach Reflexion greifen, tun Sie etwas Falsches und müssen sich fragen, warum dieser Code nicht genug über das Objekt weiß, das an ihn übergeben wurde.


3

In Fällen, in denen die Domäne der reflektierten Klassen genau definiert ist, besteht eine Alternative darin, Reflection zusammen mit anderen Metadaten zu verwenden, um Code zu generieren , anstatt Reflection zur Laufzeit zu verwenden. Ich mache das mit FreeMarker / FMPP; Es gibt viele andere Tools zur Auswahl. Dies hat den Vorteil, dass Sie am Ende "echten" Code haben, der sich leicht debuggen lässt usw.

Abhängig von der Situation kann dies dazu beitragen, dass Sie viel schnelleren Code erstellen - oder nur viel Code aufblähen. Es vermeidet die Nachteile der Reflexion:

  • Verlust der Sicherheit beim Kompilieren
  • Bugs durch Refactoring
  • langsamere Leistung

zuvor erwähnt.

Wenn das Nachdenken wie Schummeln klingt, kann es sein, dass Sie es auf eine Menge Rätselraten stützen, bei denen Sie sich nicht sicher sind, und Ihr Bauch warnt Sie, dass dies riskant ist. Stellen Sie sicher, dass Sie die Metadaten, die der Reflektion inhärent sind, durch Ihre eigenen Metadaten erweitern können. Dort können Sie alle Macken und Sonderfälle der realistischen Klassen beschreiben, denen Sie möglicherweise begegnen.


2

Es ist kein Betrug, aber wie jedes Werkzeug sollte es für das verwendet werden, was es lösen soll. Durch Reflektion können Sie per Definition Code durch Code prüfen und ändern. Wenn Sie dies tun müssen, ist Reflexion das Werkzeug für den Job. Bei der Reflexion dreht sich alles um Meta-Code: Code, der auf Code abzielt (im Gegensatz zu regulärem Code, der auf Daten abzielt).

Ein Beispiel für eine gute Reflection-Verwendung sind generische Web-Service-Schnittstellenklassen: Ein typisches Design besteht darin, die Protokollimplementierung von der Nutzlastfunktionalität zu trennen. Dann haben Sie eine Klasse (nennen wir sie T), die Ihre Payload implementiert, und eine andere, die das Protokoll ( P) implementiert . Tist ziemlich einfach: Schreiben Sie für jeden Anruf, den Sie tätigen möchten, einfach eine Methode, die das tut, was sie tun soll. PWebdienstaufrufe müssen jedoch Methodenaufrufen zugeordnet werden. Es ist wünschenswert, dieses Mapping generisch zu machen, da es Redundanz vermeidet und in Phohem Maße wiederverwendbar macht . Reflection bietet die Möglichkeit, Klassen Tzur Laufzeit zu untersuchen und ihre Methoden auf der Grundlage von Zeichenfolgen aufzurufen, die Püber das Webdienstprotokoll übergeben werden, ohne dass während der Kompilierung Kenntnisse über Klassen erforderlich sindT. Mit der Regel 'Code über Code' kann man argumentieren, dass die Klasse Pden Code in der Klasse Tals Teil ihrer Daten hat.

Jedoch.

Reflection bietet Ihnen auch Tools, mit denen Sie Einschränkungen des Typsystems der Sprache umgehen können. Theoretisch können Sie alle Parameter als Typ übergeben objectund ihre Methoden über Reflections aufrufen. Voilà, die Sprache, die eine starke statische Typisierungsdisziplin durchsetzen soll, verhält sich jetzt wie eine dynamisch typisierte Sprache mit später Bindung, nur dass die Syntax weitaus ausgefeilter ist. Jede einzelne Instanz eines solchen Musters, die ich bisher gesehen habe, war ein schmutziger Hack, und ausnahmslos wäre eine Lösung innerhalb des Typensystems der Sprache möglich gewesen, und sie wäre in jeder Hinsicht sicherer, eleganter und effizienter gewesen .

Es gibt einige Ausnahmen, z. B. GUI-Steuerelemente, die an verschiedene nicht verwandte Arten von Datenquellen gebunden werden können. Es ist nicht realistisch, dass Ihre Daten eine bestimmte Schnittstelle implementieren, damit Sie sie binden können, und der Programmierer muss auch keinen Adapter für jeden Datenquellentyp implementieren. In diesem Fall ist es sinnvoller, die Art der Datenquelle durch Reflektion zu ermitteln und die Datenbindung anzupassen.


2

Ein Problem, das wir bei Reflection hatten, ist das Hinzufügen von Obfuscation zum Mix. Alle Klassen erhalten neue Namen und das plötzliche Laden einer Klasse oder Funktion anhand ihres Namens funktioniert nicht mehr.


1

Es kommt ganz darauf an. Ein Beispiel für etwas, das ohne Reflektion nur schwer möglich wäre, wäre die Replikation von ObjectListView . Es generiert auch IL-Code im laufenden Betrieb.


1

Reflexion ist die primäre Methode zur Erstellung von konventionellen Systemen. Es würde mich nicht überraschen, dass es in den meisten MVC-Frameworks häufig verwendet wird. Es ist eine wichtige Komponente in ORMs. Möglicherweise verwenden Sie bereits Komponenten, die täglich damit erstellt werden.

Die Alternative für eine solche Verwendung ist die Konfiguration, die ihre eigenen Nachteile hat.


0

Reflexion kann Dinge bewirken, die praktisch anders nicht möglich sind.

Überlegen Sie sich beispielsweise, wie Sie diesen Code optimieren können:

int PoorHash(char Operator, int seed, IEnumerable<int> values) {
    foreach (var v in values) {
        seed += 1;
        switch (char) {
            case '+': seed += v; break;
            case '^': seed ^= v; break;
            case '-': seed -= v; break;
            ...
        }
        seed *= 3;
    }
    return seed;
}

Es gibt einen teuren Testfehler in der Mitte der inneren Schleife, aber zum Extrahieren muss die Schleife für jeden Operator einmal neu geschrieben werden. Reflexion ermöglicht es uns, die Leistung mit dem Extrahieren dieses Tests gleichzusetzen, ohne die Schleife ein Dutzend Mal zu wiederholen (und dadurch die Wartbarkeit zu beeinträchtigen). Generieren und kompilieren Sie einfach die Schleife, die Sie im laufenden Betrieb benötigen.

Ich habe diese Optimierung tatsächlich durchgeführt , obwohl die Situation etwas komplizierter war und die Ergebnisse erstaunlich waren. Eine Verbesserung der Leistung um eine Größenordnung und weniger Codezeilen.

(Hinweis: Ich habe anfangs versucht, ein Func anstelle eines Char zu übergeben, und es war etwas besser, aber nicht annähernd das 10-fache der erreichten Reflektion.)


1
Die bessere Optimierung besteht darin, stattdessen einen Funktor zu übergeben. Wird wahrscheinlich zur Laufzeit vom JIT-Compiler eingebunden und ist wartbarer als Reflektion.
Billy ONeal

Das wäre wartungsfreundlicher, und ich probiere es tatsächlich zuerst aus, aber es war nicht schnell genug. Die JIT hat es definitiv nicht implementiert, wahrscheinlich, weil es in meinem Fall eine zweite innere Schleife über die durchzuführenden Operationen gab.
Craig Gidney

Außerdem weise ich darauf hin, dass das, was Sie dort haben, wirklich selbstmodifizierender Code ist, der nicht wirklich reflektiert wird. Man greift über Reflection-APIs in den meisten Sprachen zu, die Reflection unterstützen, aber es kann genauso einfach in Sprachen erfolgen, die Reflection nicht unterstützen (z. B. wäre es in C ++ möglich)
Billy ONeal

Ich wollte das Standardbeispiel der „strukturellen Gleichheit“ vermeiden. Reflexion ist für selbstmodifizierenden Code nicht erforderlich, hilft aber auf jeden Fall.
Craig Gidney

Nicht wirklich. Sie können das in Nichtreflexionssprachen gut machen.
Billy ONeal

-2

Auf keinen Fall wird betrogen ... Vielmehr können Anwendungsserver die vom Benutzer erstellten Klassen mit dem Namen ihrer Wahl ausführen, wodurch dem Benutzer Flexibilität geboten wird, ohne sie zu betrügen.

Und wenn Sie den Code einer .class-Datei (in Java) sehen möchten, stehen Ihnen mehrere Dekompilierer kostenlos zur Verfügung!


Dekompilierung ist keine Reflektionsfunktion.
Billy ONeal

ja, ist es nicht ... aber ich wollte sagen, dass wenn du beim Verwenden der Reflektion (die dir Details zu einer Klasse in Java liefert) betrügen willst, dann bist du falsch Klasse ist, was Sie betrifft, als das mit jedem Decompiler leicht getan werden kann ...
ANSHUL JAIN

2
Reflexion ist in manchen Fällen ein nützliches Konzept, ja. Aber 99,9% der Zeit, in der ich sehe, dass es verwendet wird, wird es verwendet, um einen Entwurfsfehler zu umgehen.
Billy ONeal
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.