2011-07-08 4 views
6

私はclojureとjavaの初心者です。あなたが行うことができますClojureの中のJavaフィールドにアクセスするためにClojureでJavaフィールドに動的にアクセスしますか?

Classname/staticField 

(. Classname staticField) 

としてちょうど同じである(私が間違っているなら、私を修正)

変数の中に保持されているフィールドの名前が静的フィールドにアクセスするにはどうしたらいいですか?すなわち:

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

私はそれがフィールドにアクセスしようとする前key-strokeがシンボルVK_Lに評価されたいです。あなたは、次のような何かをしたい場合があります。この場合

+3

https://github.com/joodie/clj-java-fieldsを参照してください、あなたはJavaのリフレクションAPIを見ることができます。 http://java.sun.com/developer/technicalArticles/ALT/Reflection/のフィールドの値の変更を参照してください。 – gatoatigrado

+0

もう少し詳しく解説:フィールドまたはメソッド呼び出しのアクセスは、バイトコードでコンパイルする必要があります。そのため、ランタイム情報でそれらを構築することはできません。それが必要な場合は、リフレクションを使用する必要があります。 (Joostの答えを参照) – kotarak

答えて

9

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

それは少しハックっぽいだようにあなたが感じる場合、それは本当にそのようなので、それはです。コードを構造化するより良い方法があるかもしれませんが、少なくともこれはうまくいくはずです。

+0

この回答は役に立ちましたか?それを受け入れるように注意してください(または他の誰か)? – skuro

4

リフレクションは、おそらく取るために適切なルートですが、最も簡単な方法はこれだけで有効なのClojureに生成された文字列を変換し、それを評価します

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

です。

1

あなたはs-expressionとして右の呼び出しを構築し、次のように評価することができます。

(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") 
6

私はリフレクションAPIを使用してClojureのマップにpublicフィールドを変換する小さなClojureのライブラリを作った:

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

がskuroの答えに加えて