我正在学习如何在Clojure中扩展Java类,但是我没有看到声明新成员变量的方法;我只看到了一种方法。
(ns test.aclass
(:gen-class
:methods [[foo [] String]]))是否有:members关键字或其他方式来声明成员变量?
发布于 2009-10-18 05:41:36
:state name
如果提供,将创建具有给定名称的公共最终实例字段。必须提供:init函数才能为状态提供值。请注意,虽然是最终的,但状态可以是ref或agent,支持创建具有事务性或异步突变语义的Java对象。
在website上有一个如何使用它的示例。
发布于 2012-01-06 20:30:39
我在这方面也遇到了一些麻烦。下面的示例并不优雅,但对于用Clojure而不是Java编写愚蠢的小glue类来说,它是相当简单的。注我为线程安全所做的所有工作就是确保字段更新是原子的--我没有做任何其他并发的事情,这可能会产生真正的不同。
init方法为对象创建实例变量。setfield和getfield宏简化了原子更新的记账工作。
(ns #^{:doc "A simple class with instance vars"
:author "David G. Durand"}
com.tizra.example )
(gen-class
:name com.tizra.example.Demo
:state state
:init init
:prefix "-"
:main false
:methods [[setLocation [String] void]
[getLocation [] String]]
)
(defn -init []
"store our fields as a hash"
[[] (atom {:location "default"})])
(defmacro setfield
[this key value]
`(swap! (.state ~this) into {~key ~value}))
(defmacro getfield
[this key]
`(@(.state ~this) ~key))
(defn -setLocation [this ^java.lang.String loc]
(setfield this :location loc))
(defn ^String -getLocation
[this]
(getfield this :location))你必须编译它,并确保生成的存根类在你的类路径上,然后你就可以像其他java类一样创建实例,等等。
=> (com.tizra.example.Demo.)
#<Demo com.tizra.example.Demo@673a95af>
=> (def ex (com.tizra.example.Demo.))
#'user/ex
=> (.getLocation ex)
"default"
=> (.setLocation ex "time")
nil
=> (.getLocation ex)
"time"我发现这个博客上的较长的摘要很有帮助:http://kotka.de/blog/2010/02/gen-class_how_it_works_and_how_to_use_it.html
发布于 2012-01-07 03:38:41
proxy的主体是一个词法闭包,因此您可以根据需要对任何变量进行闭合。如果,上帝保佑,你需要改变它们,然后关闭一个原子:
(defn lying-list [init-size]
(let [the-size (atom init-size)]
(proxy [java.util.ArrayList] []
(size [] @the-size)
(remove [idx] (reset! the-size idx), true))))这里真的不需要实际的Java字段。
https://stackoverflow.com/questions/1584054
复制相似问题