2011-07-08 9 views
6

Soy un novato en clojure y java.¿Tiene acceso a los campos Java dinámicamente en Clojure?

Con el fin de acceder a un campo de Java en Clojure que puede hacer:

Classname/staticField 

cual es lo mismo que

(. Classname staticField) 

(corríjanme si me equivoco)

¿Cómo puedo acceder a un campo estático cuando el nombre del campo se mantiene dentro de una variable? es decir .:

(let [key-stroke 'VK_L 
     key-event KeyEvent/key-stroke]) 

Quiero key-stroke a ser evaluados en el símbolo VK_L antes de que intenta acceder al campo.

+3

Además de la respuesta de skuro, se puede ver en la API de reflexión de Java. Consulte la sección "Cambio de valores de los campos" en http://java.sun.com/developer/technicalArticles/ALT/Reflection/. – gatoatigrado

+0

Para explicar un poco más: El acceso de los campos o las llamadas a los métodos deben compilarse en el código de bytes. Es por eso que no puedes construirlos con información de tiempo de ejecución. Si lo necesitas, tendrás que usar el reflejo. (ver la respuesta de Joost) – kotarak

Respuesta

9

En este caso es posible que desee hacer algo como lo siguiente:

user=> (def m 'parseInt)   
#'user/m 
user=> `(. Integer ~m "10")  
(. java.lang.Integer parseInt "10") 
user=> (eval `(. Integer ~m "10")) 
10 

Si usted se siente como que es un poco hack-ish, es porque realmente es así. Puede haber mejores formas de estructurar el código, pero al menos esto debería funcionar.

+0

¿Te ayudó esta respuesta? ¿Te importa aceptarlo (o el de otra persona)? – skuro

4

La reflexión es probablemente la ruta correcta a tomar, pero la forma más fácil es

(eval (read-string (str "KeyEvent/" key-stroke))) 

esto sólo convertir la cadena generada en clojure válida y luego evaluarla.

1

Es posible construir la decisión correcta como s-expression y evaluar de la siguiente manera:

(let [key-stroke 'VK_L 
     key-event (eval `(. KeyEvent ~key-stroke))] 
    ....do things with your key-event......) 

Sin embargo, si lo que estamos tratando de hacer es comprobar si una clave particular ha sido presionado, es posible que no necesita ningún de esto: por lo general encuentran que es más fácil de escribir código algo como:

(cond 
    (= KeyEvent/VK_L key-value) 
    "Handle L" 
    (= KeyEvent/VK_M key-value) 
    "Handle M" 
    :else 
    "Handle some other key") 
6

hice una pequeña biblioteca clojure que se traduce campos públicos a clojure mapas utilizando el API de reflexión:

(ns your.namespace 
(:use nl.zeekat.java.fields)) 

(deftype TestType 
    [field1 field2]) 

; fully dynamic: 

(fields (TestType. 1 2)) 
=> {:field1 1 :field2 2} 

; optimized for specific class: 
(def-fields rec-map TestType) 

(rec-map (TestType. 1 2)) 
=> {:field1 1 :field2 2} 

Ver https://github.com/joodie/clj-java-fields

Cuestiones relacionadas