Доступ к полям Java динамически в Clojure? - PullRequest
7 голосов
/ 09 июля 2011

Я новичок в clojure и java.

Чтобы получить доступ к полю Java в Clojure, вы можете сделать:

Classname/staticField

, что аналогично

(. Classname staticField)

(поправьте меня, если яневерно)

Как получить доступ к статическому полю, если имя поля содержится в переменной? т.е.:

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

Я хочу key-stroke, чтобыбыть оцененным в символ VK_L, прежде чем он попытается получить доступ к полю.

Ответы [ 4 ]

10 голосов
/ 09 июля 2011

В этом случае вы можете сделать что-то вроде следующего:

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

Если вы чувствуете, что это немного хакерство, то это потому, что это действительно так. Возможно, есть лучшие способы структурировать код, но, по крайней мере, это должно сработать.

6 голосов
/ 10 июля 2011

Я создал небольшую библиотеку clojure, которая переводит открытые поля в карты clojure с помощью API отражения:

(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}

См. https://github.com/joodie/clj-java-fields

4 голосов
/ 09 июля 2011

Отражение - это, вероятно, правильный путь, но самый простой путь -

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

Это просто преобразует сгенерированную строку в допустимое замыкание и затем оценивает ее.

1 голос
/ 09 июля 2011

Вы можете создать правильный вызов как s-выражение и оценить его следующим образом:

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

Однако, если вы пытаетесь проверить, является ли конкретный ключнажата, вам может не понадобиться ничего из этого: я обычно нахожу, что проще всего написать код вроде:

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