2011-07-08 24 views
6

Tôi là người mới trong clojure và java.Truy cập các trường Java tự động trong Clojure?

Để truy cập vào một lĩnh vực Java trong Clojure bạn có thể làm:

Classname/staticField 

mà chỉ là giống như

(. Classname staticField) 

(đúng cho tôi nếu tôi sai)

Làm cách nào để truy cập trường tĩnh khi tên của trường được giữ trong một biến? tức là .:

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

Tôi muốn key-stroke được đánh giá vào biểu tượng VK_L trước khi nó cố gắng để truy cập vào lĩnh vực này.

+3

Ngoài câu trả lời của skuro, bạn có thể xem API phản chiếu Java. Xem phần "Thay đổi giá trị của các trường" tại http://java.sun.com/developer/technicalArticles/ALT/Reflection/. – gatoatigrado

+0

Để khai thác thêm một chút: Truy cập các trường hoặc các cuộc gọi phương thức phải được biên dịch trong mã byte. Đó là lý do tại sao bạn không thể xây dựng chúng với thông tin thời gian chạy. Nếu bạn cần điều đó, bạn sẽ phải sử dụng sự phản chiếu. (xem câu trả lời của Joost) – kotarak

Trả lời

9

Trong trường hợp này bạn có thể muốn làm điều gì đó như sau:

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

Nếu bạn cảm thấy như đó là một chút hack-ish, đó là bởi vì nó thực sự là như vậy. Có thể có những cách tốt hơn để cấu trúc mã, nhưng ít nhất điều này cũng có tác dụng.

+0

Câu trả lời này có giúp ích cho bạn không? Chăm sóc để chấp nhận nó (hoặc của người khác)? – skuro

4

Reflection có lẽ là con đường đúng đắn để đi, nhưng cách đơn giản nhất là

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

này chỉ sẽ chuyển đổi các chuỗi được tạo ra vào clojure hợp lệ và sau đó đánh giá nó.

1

Bạn có thể xây dựng cuộc gọi đúng như một s-expression và đánh giá nó như sau:

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

Tuy nhiên, nếu những gì bạn đang cố gắng làm là kiểm tra xem một phím đặc biệt đã được ép, bạn có thể không cần bất kỳ điều này: tôi thường thấy rằng nó là dễ nhất để viết mã một cái gì đó như:

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

tôi đã thực hiện một thư viện clojure nhỏ mà dịch các lĩnh vực công cộng để Clojure bản đồ bằng cách sử dụng API phản ánh:

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

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

Các vấn đề liên quan