Параметры для создания классов Java в Clojure

Существует несколько различных способов создания классов Java в Clojure, поэтому каковы компромиссы при выборе между gen-class, proxy и reify в Clojure? (Существуют ли другие способы создания классов Java, которые я еще не перечислял?)

Мое основное понимание состоит в том, что я перечислил эти конструкции в порядке убывания мощности.

Ответы

Ответ 1

Используйте gen-class, если вам нужен именованный класс, или вы хотите добавить новые методы к создаваемым вами объектам. gen-class опирается на компиляцию AOT.

Если вы хотите анонимную однократную реализацию типа, используемого reify или proxy. Они не полагаются на компиляцию AOT. Вот их отличия:

  • reify поддерживает только протоколы или интерфейсы, proxy также поддерживает конкретные суперклассы.
  • reify использует методы истинного класса, proxy использует внешние функции.
  • Из-за # 2 reify использует прямой поиск метода, а proxy использует карту для поиска метода.
  • Из-за # 3 reify не поддерживает динамическую замену методов, но proxy делает.

reify будет работать лучше, чем proxy, поэтому вы всегда должны использовать reify, когда это возможно. Используйте только proxy, когда ограничения reify слишком запретительны.

Ответ 2

В дополнение к gen-class, proxy и reify, у нас есть defrecord и deftype. Эти последние два варианта должны быть вашими первыми выборами для создания названных классов java (а в случае defrecord - ваш первый выбор для любой структуры с именованными компонентами.)

Страница datatypes на clojure.org является хорошей ссылкой на эту тему. Defrecord, deftype и reify новее, чем gen-class и proxy, были представлены в версии 1.2 (я думаю - возможно, 1.1). Defrecord и deftype создают как классы, соответствующие интерфейсам, но не допускающие наследования. Если вам требуется наследование, gen-class (и прокси для анонимных классов) по-прежнему остается вашим единственным вариантом.

Defrecord и deftype отличаются тем, что вам дают бесплатно. Defrecord автоматически создает класс, который соответствует IPersistentMap и ISeq. С другой стороны, Deftype дает вам больше контроля над вашим классом, даже учитывая изменяемые поля (не разрешенные в defrecord). В общем, deftype предназначен для низкоуровневой реализации структур данных, тогда как defrecord предназначен для повседневного использования.