Переопределение равняется, хэш-код и toString в Clojure deftype

Я пытаюсь создать новый тип в Clojure с помощью deftype для реализации двумерного (x, y) координата, которая реализует протокол "Местоположения".

Я также хотел бы иметь эту реализацию, которой стандартный Java равняется, хэш-код и 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 параметр протокол Местоположения.

Каков правильный подход? Я на правильном пути?

10
задан jjnguy 10 June 2010 в 20:46
поделиться

1 ответ

Чтобы проверить, удовлетворяет ли что-либо протоколу, существует удовлетворяет? .

Редактировать:

Протоколы и типы данных слишком новы в 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

Возможно, что defrecord -defined вещи когда-нибудь будут иметь собственный синтаксис читателя в Clojure, поэтому их можно будет распечатать и прочитать обратно с помощью читателя Clojure. Если вы действительно не привязаны к своей версии toString , вы также можете иметь это в виду. Прямо сейчас записи уже печатаются для человека, если не для машинного чтения.

user> (Point. 1 2)
#:user.Point{:x 1, :y 2}
7
ответ дан 4 December 2019 в 02:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: