In a project using clojure.java.jmx
, I was extending it's Destract
protocols objects->data
function to transform more of the JMX data structures returned from calls or metadata queries into plain clojure data structures.
When I was done with the individual data structures, it should have been possible to do a (walk/prewalk jmx/objects->data (jmx/operations "java.lang:type=Threading"))
.
However, in the Destract
protocol there's an implementation of the objects->data
function for the type clojure.lang.Associative
that would mean maps would be processed incorrectly.
I could add an implementation for clojure.lang.IPersistentMap
in my namespace, but since clojure.lang.Associative
is also an interface for maps this would not work.
I ended up having to fork clojure.java.jmx
because of it. If there would be a way to change preference, or retract a protocol for a type within another namespace I wouldn't have had to.
Is there a way to prevent clojure.lang.Associative
taking precedence over clojure.lang.IPersistentMap
in the protocol ?
If there isn't, is it possible to retract a protocol for a type in another namespace ? Would it even be possible to implement it in regard to the way protocols are compiled into Java interfaces ?
It should work
Are you sure that providing your own implementation for
clojure.lang.IPersistentMap
won't work? It works in my REPL session. It even works when I just override the default implementation forclojure.lang.Associative
:It also works in a sample project.
You must remember to
require
the namespace where youextend-protocol
if it's not loaded transitively by another namespace. It's important that yourextend-protocol
will be loaded after the one you would like to override.Internally
extend-protocol
orextend-type
modify a special map attached to protocol's metadata where itassoc
s a given type with a function implementation. If there was an existing entry for a given type it will be overridden. Thus the order in whichextend-*
are executed is important.When it won't work
When an object implements an interface or a protocol directly (e.g. inline in
defrecord
) you cannot override the implementation (continued REPL session):