2015-05-01 13 views
6

This answer auf eine sehr alte Frage über Clojure-Java-Interop erstellen erklärt, wie gen-class mit den :state und :init Keywords verwenden, um eine einzige öffentliche Instanz-Variable zugänglich von Java zu erstellen. Dies ist ausreichend, wenn Sie nur einen Teil der Daten für Java-Klassen verfügbar haben müssen oder wenn Sie von den Java-Klassen verlangen können, dass sie Accessor-Funktionen verwenden, die z. B. eine in der Statusvariablen gespeicherte Map lesen. Dieses Verfahren ermöglicht auch, dass sich die Daten ändern, z. durch Speichern von atom s in der Statusvariablen.Wie mehrere Java-Membervariablen mit Clojure der gen-Klasse

Was ist, wenn ich mehr als eine Instanzvariable erstellen möchte, die direkt in einer Java-Klasse lesbar ist? Ist das möglich? Zum Beispiel kann ich die folgenden Dateien kompilieren und die Klasse Bar ausführen und den Wert 42 von foo.bar ausgedruckt sehen.

Foo.clj:

(ns students.Foo 
    (:gen-class 
    :name students.Foo 
    :state bar 
    ; :state baz 
    :init init)) 

(defn -init 
    [] 
    [[] 42]) 

Bar.java:

package students; 

public class Bar { 

    public static void main(String[] args) { 
     Foo foo = new Foo(); 
     System.out.println(foo.bar); 
     // System.out.println(foo.baz); 
    } 
} 

Wenn ich die baz Linien Kommentar-, Bar.java nicht kompiliert - der Compiler scheint zufällig erstellen entweder bar oder baz als die Statusvariable für Foo, so dass nur eine von ihnen verfügbar ist Bar. Und auf jeden Fall sehe ich nicht, wie man sowohl bar als auch baz mit einer init Funktion initialisiert.

Antwort

2

Der Makro gen-class unterstützt nicht die Definition von mehr als einem öffentlichen Feld. Sie müssen stattdessen das Makro defrecord oder das Makro deftype verwenden.

(defrecord Foo [bar baz]) 

Leider sowohl die defrecord Makro und das deftype Makro vorbereiten keine Möglichkeit, ihre Erbauer zu definieren. Wenn also mehrere Instanzvariablen initialisiert werden müssen, ist es keine Schande, eine Java-Klasse in Java zu schreiben.

+0

Danke. Keine Schande, aber kein Spaß; Ich schreibe lieber Clojure. Es ist enttäuschend. Angesichts all der Möglichkeiten, die Clojure für die Interaktion mit Java bietet, scheint dies eine willkürliche Einschränkung zu sein. Mehrere Instanzvariablen sind glücklicherweise nicht zwingend für mich, aber ich wollte es wissen. – Mars

+0

Basierend auf [Chas Emericks Flowchart für die Wahl des richtigen Clojure-Definitionsformulars] (http://cemerick.com/2011/07/05/flowchart-for-choosing-the-right-clojure-type-definitionform), 'gen-class' ist wahrscheinlich die beste Option für mein aktuelles Projekt. – Mars