Dies ist eine Mischung aus drei verschiedenen Faktoren:
- Das spezielle Typsystem des JVM
- Die Notwendigkeit einer leicht unterschiedlichen Semantik für unterschiedliche Anwendungsfälle bei der Definition von Typen
- Die Tatsache, dass einige davon früher und andere später entwickelt wurden, als sich die Sprache weiterentwickelt hat.
Lassen Sie uns zunächst überlegen, was diese tun. Deftype und Gen-Klasse sind insofern ähnlich, als sie beide eine benannte Klasse für die vorzeitige Kompilierung definieren. Gen-Klasse stand an erster Stelle, gefolgt von Deftype in Clojure 1.2. Deftype wird bevorzugt und weist bessere Leistungseigenschaften auf, ist jedoch restriktiver. Eine Deftype-Klasse kann einer Schnittstelle entsprechen, aber nicht von einer anderen Klasse erben.
Reify und Proxy werden beide verwendet, um zur Laufzeit dynamisch eine Instanz einer anonymen Klasse zu erstellen. Proxy stand an erster Stelle, Reify kam zusammen mit Deftype und Defrecord in Clojure 1.2. Reify wird ebenso bevorzugt wie Deftype, bei dem die Semantik nicht zu restriktiv ist.
Das lässt die Frage offen, warum sowohl Deftype als auch Defrecord, da sie gleichzeitig auftraten und eine ähnliche Rolle spielen. Für die meisten Zwecke werden wir Defrecord verwenden wollen: Es hat all die verschiedenen Clojure-Güte, die wir kennen und lieben, Sequenzierbarkeit und so weiter. Deftype ist als Baustein auf niedriger Ebene für die Implementierung anderer Datenstrukturen vorgesehen. Es enthält keine regulären Clojure-Schnittstellen, bietet jedoch die Möglichkeit, Felder zu ändern (obwohl dies nicht die Standardeinstellung ist).
Weitere Informationen finden Sie unter:
Die Seite mit den Datentypen von clojure.org
Der Google-Gruppenthread, in dem Deftype und Reify eingeführt wurden
proxy
wird manchmal bevorzugt, weil es die Änderung von Methoden zur Laufzeit ermöglicht. (zB The Joy of Clojure , 2. Ausgabe, schlägt vor, dass dies nützlich sein könnte, um Rückrufe in einem Web-Handler zu ändern.)Die kurze Antwort lautet, dass sie alle unterschiedliche und nützliche Zwecke haben. Die Komplexität beruht auf der Notwendigkeit, effektiv mit verschiedenen Funktionen der zugrunde liegenden JVM zusammenzuarbeiten.
Wenn Sie kein Java-Interop benötigen, halten Sie sich in 99% der Fälle am besten an Defrecord oder eine einfache Clojure-Map.
Wenn Ihre Anforderungen komplexer sind, ist das folgende Flussdiagramm ein hervorragendes Werkzeug, um zu erklären, warum Sie eine dieser Optionen gegenüber den anderen auswählen würden:
http://cemerick.com/2011/07/05/flowchart-for-choosing-the-right-clojure-type-definition-form/
quelle