1

I recently asked why interfaces and protocols could be incompletely implemented in clojure:

user=> (defprotocol P (foo [self])) P user=> (extend-type Long P) nil user=> (extends? P Long) true user=> (foo 1) IllegalArgumentException No implementation of method: :foo of protocol: #'user/P found for class: java.lang.Long clojure.core/-cache-protocol-fn (core_deftype.clj:527) 

and was told that this was for interop reasons and that it wouldn't be a problem in practice. Sure.

But apparently extends? really tells me nothing about the relationship between a protocol and a class: just as (extends? P C) does not imply that I can call foo on objects of class C, (not (extends? P C)) does not imply that I cannot call foo on objects of class C:

user=> (defprotocol P (foo [self])) P user=> (extend-type Object P (foo [self] 1)) nil user=> (extends? P Long) false user=> (foo 1) 1 

Now I am very confused about what information extends? is supposed to give me... satisfies?, on the other hand, handles the second case correctly, but not the first one.

1 Answer 1

3

When in doubt check the code :). The implementation of extends? is this:

(defn extends? "Returns true if atype extends protocol" {:added "1.2"} [protocol atype] (boolean (or (implements? protocol atype) (get (:impls protocol) atype)))) 

So it just check if the atype has been extended by the protocol and it doesn't mean it has implemented all the methods of the protocol.

The :impls is a map where key is the type that extended the protocol and the value is map which has the methods implementation of the protocol for the type.

user=> (defprotocol hello (a [self])) hello user=> (:impls hello) nil user=> (extend-type String hello) nil user=> (:impls hello) {java.lang.String {}} user=> (extend-type String hello (a [self] 10)) nil user=> (:impls hello) {java.lang.String {:a #<user$eval613$fn__614 user$eval613$fn__614@1d978ea>}} 

On the other hand to satisfies? you need to pass the object on which you want to check for protocol and not the type as in case of extends? So if you look at satisfies? code it is a bit more complex then extends as it has to check the base classes of the object being passed for being extended by protocol. But both the functions just check whether there the type (or base types) has extended the protocol or not AND they don't check if you have actually implemented the protocol methods or not.

Sign up to request clarification or add additional context in comments.

2 Comments

Sure, I went and had a look at the code, but what I'm really looking for is more "what behaviour can I expect from a class that responds yes when asked whether it extends a protocol?".
You can expect that the type has extended and implemented the protocol methods (hopefully following good coding convention and implementing each method of the protocol), so call the protocol method on the object of that type should work in case the particular protocol method is implemented by the type

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.