我试图用Clojure创建一个新的类型,使用deftype来实现一个二维(x,y)坐标,它实现了一个“位置”协议. 我也希望这样实现标准的Java equals,hashCode和toString方法. 我的初步尝试是: (defprotocol Lo
我也希望这样实现标准的Java equals,hashCode和toString方法.
我的初步尝试是:
(defprotocol Location (get-x [p]) (get-y [p]) (add [p q])) (deftype Point [#^Integer x #^Integer y] Location (get-x [p] x) (get-y [p] y) (add [p q] (let [x2 (get-x q) y2 (get-y q)] (Point. (+ x x2) (+ y y2)))) Object (toString [self] (str "(" x "," y ")")) (hashCode [self] (unchecked-add x (Integer/rotateRight y 16))) (equals [self b] (and (XXXinstanceofXXX Location b) (= x (get-x b)) (= y (get-y b)))))
但是,如果b参数实现了Location协议,那么equals方法仍然需要一些解决方法.
什么是正确的方法?我在正确的轨道上吗?
为了测试是否符合协议,有satisfies?
.
编辑:
Clojure中的协议和数据类型太新了(而且还在快速发展),对于我来说,很多都是惯用语.但是你应该注意到,defrecord已经实现了基于类型和价值的平等.除非你真的需要一个自定义哈希码的对象,你可以考虑使用defrecord.
(defrecord Point [#^Integer x #^Integer y] Location (get-x [p] x) (get-y [p] y) (add [p q] (let [x2 (get-x q) y2 (get-y q)] (Point. (+ x x2) (+ y y2))))) user> (= (Point. 1 2) {:x 1 :y 2}) false user> (= (Point. 1 2) (Point. 1 2)) true
您还可以通过关键字查找获得额外的好处,并可以将元数据放在您的对象上,哪些defrecord可以免费提供给您.
user> (:x (Point. 1 2)) 1
有可能Defracord定义的东西将有一天在Clojure定制阅读器的语法,所以他们可以被可读地打印和回读与Clojure读者.除非你真的附加到你的toString版本,否则你也可以记住这一点.现在,如果不是机器可读的,记录已经可人性化地印刷.
user> (Point. 1 2) #:user.Point{:x 1, :y 2}