Прежде всего, протоколы являются определениями интерфейса, и, как правило, вы не хотите указывать состояние в интерфейсе.Как правило, вы хотите поместить состояние в реализацию интерфейса, см. Ниже.
Для большинства конструкций clojure, которые позволяют реализовывать интерфейсы или расширять классы наиболее подходящим способом, особенно если выне владеть классом - это использовать замыкания для захвата состояния.Вы можете захватывать изменяемые типы для реализации изменяемого состояния (хотя это , вероятно, то, чего вы хотите избежать, если можете).
Неизменяемый пример из http://clojure.github.com/clojure/clojure.core-api.html#clojure.core/reify
(str (let [f "foo"]
(reify Object
(toString [this] f))))
Обратите внимание, что f здесь может быть ref или var или atom вместо строки, если вы хотите изменяемое состояние.
РЕДАКТИРОВАТЬ: как отмечено в комментариях, я, возможно, не сделал это полностью ясно: вы можетеиспользуйте defprotocol для определения интерфейса на основе функций, а затем используйте reify для создания экземпляров этого протокола для захвата состояния.
РЕДАКТИРОВАТЬ 2: Извините за то, что я запутался.Этот код на самом деле не будет работать для существующих классов, потому что reify не поддерживает его.Прокси, вероятно, работает как альтернатива, хотя в документации не указано, что имена функций в карте протокола 1-1 соответствуют интерфейсным методам.