Параметры для создания классов 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 предназначен для повседневного использования.