我想在Clojure中创建一个具有属性和方法的对象,我读到gen-class和proxy可以完成我需要的工作但是它的实现对我来说非常混乱。
我想使用代理来避免AOT编译步骤,我读到它并且我虽然我更好地学习如何使用更容易的两个
这是我想在Clojure中做的事情
Java代码:
public class MyClass {
public float myFloat;
MyClass( float _myFloat ) {
myFloat = _myFloat
}
public void showNumber() {
println( myFloat );
}
}
我正在努力使用代理将代码转换为Clojure,任何帮助都将非常感激
更新
显然 deftype 更适合我的目的,但我仍然在努力实施
这是我的Clojure代码:
(deftype Particle [x y]
Object
(render [this]
(no-stroke)
(fill 200 30 180)
(ellipse x y 200 200)))
我需要指定一个协议,我不确定要使用哪个协议,所以我正在使用Object,因为我正在尝试创建类似于java的对象但是我得到了以下错误消息:< / p>
无法在接口中定义方法:render
我正在使用quill,这是Clojure的处理端口,如果这有帮助
更新2:
好吧我设法得到一个有效的defprotocol和deftype组合,但还有一件事我需要学习如何做,那就是向我的班级添加成员变量或属性,这是我的clojure代码:
(defprotocol ParticleProtocol
(update [this])
(render [this]))
(deftype Particle [position]
ParticleProtocol
(update [this])
(render [this]
(no-stroke)
(fill 200 30 180)
(ellipse (.x position) (.y position) 20 20)))
对于这个对象,我想添加一些像radius这样的变量,任何想法?
答案 0 :(得分:3)
我同意在{Clojure中deftype
(或可能defrecord
)比proxy
更好,但最后请看我的评论以考虑所有可能性。
对于UPDATE 2之后的问题。
您可以通过在arglist中指定它们来为记录添加“属性”:
(deftype Particle [position radius prop3 prop4]
...
)
请记住,Clojure中的类型是不可变的,因此在创建实体后没有设置属性的概念。如果某些属性是可选的,建议最佳做法是创建辅助“工厂”方法,例如:
(defn make-particle
([position] (Particle. position nil nil nil))
([position radius] (Particle. position radius nil nil))
;; etc. add more here as needed
)
要考虑的一个选项是完全删除类型,只使用地图,其中包含您需要的“属性/字段”。当您需要实现抽象时,类型很有用。对于您的ParticleProtocol - 它提供的价值是多少?协议旨在提供一种具有多态性的方法,那么您将拥有此协议的多个实现吗?
Chas Emerick深入介绍了如何在Clojure中选择可能对您有帮助的数据类型:http://cemerick.com/2011/07/05/flowchart-for-choosing-the-right-clojure-type-definition-form/
[更新显示示例地图实施] :
使用“属性”构建地图并检索该属性:
(def mymap {:myfloat 3.1415926})
(println "myfloat has value:" (:myfloat mymap))
要提供其他功能,例如“渲染”功能,只需创建一个接受带有所需键的地图的fn:
;; the details are bogus, just showing the syntax
(defn render [m]
(no-stroke)
(fill (:radius m) (:position m))
(do-something-else (:position m)))
对于update
,如果您要更新粒子贴图中的值,则需要创建新贴图,而不是更新现有贴图。
(def myparticle {:position 100 :radius 25})
(defn change-pos [particle-map new-pos]
(assoc-in particle-map [:position] new-pos))
(let [new-particle (change-pos myparticle 300)]
(println new-particle))
;; prints out {:position 300 :radius 25}
;; orig myparticle still has value {:position 100 :radius 25}
;; or do it directly
(println (assoc myparticle :position 300))
;; prints out {:position 300 :radius 25}
答案 1 :(得分:1)
您可以在position
旁边添加“变量”,如下所示:
(deftype Particle [position radius]
...
)
position
和radius
不是真正的变量,它们更像是final
属性。如果你需要“改变”它们,你应该将原子存储在它们中,如下所示:
(Particle. (atom (Position. 3 4)) (atom 5.0))
但是你应该注意@ m0skit0的建议,不再考虑对象和类,并开始考虑函数和不可变数据结构。