По умолчанию
deftype
поля все еще неизменны; чтобы переопределить это, вам нужно аннотировать имена полей, которые должны быть изменяемыми, с соответствующими метаданными. Кроме того, синтаксис для set!
полей экземпляра отличается. Пример реализации, чтобы заставить работать выше:
(deftype Point [^{:volatile-mutable true} x]
IPoint
(getX [_] x)
(setX [this v] (set! x v)))
Там также :unsynchronized-mutable
. Разница заключается в том, как имена могут предложить опытному разработчику Java. ;-) Обратите внимание, что предоставление любой аннотации имеет дополнительный эффект, делающий поле частным, так что прямой доступ к полю больше невозможен:
(.getX (Point. 10)) ; still works
(.x (Point. 10)) ; with annotations -- IllegalArgumentException, works without
Кроме того, 1.2, вероятно, будет поддерживать синтаксис ^:volatile-mutable x
в качестве сокращения для ^{:volatile-mutable true} x
(это уже доступно в некоторых новых числовых ветвях).
Оба варианта упомянуты в (doc deftype)
; соответствующая часть следует - учтите предостережение!
Поля могут быть квалифицированы
с метаданными: volatile-mutable true или: unsynchronized-mutable
true, в какой момент (set! afield aval) будет поддерживаться в методе
тела. Обратите внимание, что изменяемые поля чрезвычайно сложно использовать
правильно, и присутствуют только для облегчения строительства высшего
конструкции уровня, такие как ссылочные типы Clojure, в Clojure
сам. Они только для экспертов - если семантика и
последствия: volatile-mutable или: unsynchronized-mutable не являются
Сразу видно, вы не должны их использовать.