На одном уровне проблема в том, что JVM не позволяет обмениваться реализациями методов между классами, поскольку реализация встроенного протокола означает, что класс, созданный defrecord
, реализует интерфейс, соответствующий протоколу.Обратите внимание, что, хотя выбор сделать это жертвует некоторой гибкостью, он также покупает скорость - и, действительно, скорость является основным соображением при проектировании.
На другом уровне это, как правило, очень плохая идея для реализаций протокола для типов, которые должны быть предоставлены кодом, которому не принадлежит ни тип, ни рассматриваемый протокол.См., Например, эту ветку в группе Google Clojure для обсуждения по теме (включая заявление Rich Hickey);есть также соответствующая запись в Стандартах кодирования библиотеки Clojure :
Протоколы:
- Протокол следует распространять только на тип, если он владеетлибо тип, либо протокол.
- Если кто-то нарушает предыдущее правило, он должен быть готов отказаться, если разработчик любого из них предоставит определение
- Если протокол поставляется с самой Clojure, избегайтерасширение его до типов, которые вам не принадлежат, особенно, например, java.lang.String и другие основные интерфейсы Java.Будьте уверены, что если протокол будет распространяться на него, он будет лоббировать его.
- Мотив, как заявил Рич Хикки, [предотвращать] «люди распространяют протоколы на типы, для которых они не имеют смысла, например, для которых авторы протокола рассматривали, но отклоняли реализацию из-за семантикинесоответствие.".«Никакого расширения не будет (по замыслу), и люди без достаточного понимания / навыков могут заполнить пустоту неработающими идеями».
Это также обсуждалосьмного в сообществе Haskell в связи с классами типов (google "orphan экземпляры"; здесь также есть несколько хороших постов на эту тему в SO).
Теперь явно встроенная реализация всегда предоставляется владельцемтип и т. д. не должен заменяться клиентским кодом.Итак, я вижу два действительных варианта использования для замены метода протокола:
тестирование в REPL и применение быстрых настроек;
изменение реализаций метода протокола в работающем образе Clojure.
(1) может представлять меньшую проблему, если во время разработки использовать extend
& Co. и переключаться на встроенные реализации только внекоторая поздняя стадия настройки производительности;(2) это просто то, чем можно пожертвовать, если требуется максимальная скорость.