当前位置 : 主页 > 大数据 > 区块链 >

在Clojure deftype中覆盖equals,hashCode和toString

来源:互联网 收集:自由互联 发布时间:2021-06-22
我试图用Clojure创建一个新的类型,使用deftype来实现一个二维(x,y)坐标,它实现了一个“位置”协议. 我也希望这样实现标准的Java equals,hashCode和toString方法. 我的初步尝试是: (defprotocol Lo
我试图用Clojure创建一个新的类型,使用deftype来实现一个二维(x,y)坐标,它实现了一个“位置”协议.

我也希望这样实现标准的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}
网友评论