Object is a little special, yes, so it was a bad example for me to use. But 
the code used for deciding which protocol implementation to use is pretty 
straightforward<https://github.com/clojure/clojure/blob/c0b81aa9d7ef30a5c252367c162bf7fb410ea4d7/src/clj/clojure/core_deftype.clj#L483-L502>
.

   1. If the class implements the protocol's associated interface directly, 
   call through that
   2. If the object's class has been extended to the protocol specifically, 
   use that implementation
   3. Walk up the superclass chain (not including Object), seeing if any of 
   the concrete classes this class extends support the protocol. If so, use 
   the first one you find (which will be the most-derived class with an 
   implementation).
   4. Look through the set of all interfaces implemented by this object, 
   and see if the protocol is extended to any of them. If only one interface 
   supports the protocol, use it. If two interfaces X and Y both support the 
   protocol, and X is a superinterface of Y, then Y is preferred over X; 
   otherwise, the implementation is chosen arbitrarily.
   5. Finally, if the protocol is extended to Object, use that 
   implementation

Now, that's a description of the current implementation, and not any 
documented guarantee, but it seems like Rich went to a lot of effort to 
ensure that if you extend to a class (or interface) and its subclass (or 
subinterface), then the most concrete implementation will be used. I really 
don't think this will change in any Clojure version, and think this is 
something that you can safely rely on for your protocol implementations.

On Friday, May 10, 2013 3:16:18 PM UTC-7, David Nolen wrote:
>
> It was my impression that extending to Object is handled as a special case 
> - much like extend-type default in ClojureScript.
>
>
> On Fri, May 10, 2013 at 6:06 PM, Alan Malloy <al...@malloys.org<javascript:>
> > wrote:
>
>> Even when the interface and class you've extended them to are related by 
>> inheritance? I thought the most-derived implementation was chosen, and only 
>> when there's a "tie" like a class that implements two unrelated interfaces, 
>> both of which have had the protocol extended to them. If it were completely 
>> undefined, all sorts of useful idioms would become untenable. For example, 
>> you couldn't extend a protocol to Object and also to various other classes. 
>> Dave's scenario is like this, in which TUnion is more-derived than TBase, 
>> and so as far as I know should always "win" in the polymorphic dispatch. 
>> Reading through core_deftype's functions 'pref and 'find-protocol-impl seem 
>> to support this assertion; am I missing something?
>>
>> On Friday, May 10, 2013 2:20:31 PM UTC-7, Stuart Sierra wrote:
>>>
>>> When you extend a protocol to multiple Java interfaces / abstract 
>>> classes, then call the methods on an instance which implements/extends more 
>>> than one of those, the result is *undefined*.
>>>
>>> The problem is that this permits multiple inheritance of concrete 
>>> behavior, the reason Java doesn't allow multiple base classes.
>>>
>>> Protocols do not (currently) have any mechanism to "prefer" one method 
>>> implementation over another.
>>>
>>> In general, I recommend extending protocols only to concrete types, not 
>>> interfaces.
>>>
>>> -S
>>>
>>>
>>> On Friday, May 10, 2013 4:45:57 AM UTC+10, Dave Kincaid wrote:
>>>>
>>>> I've not worked with protocols much, but saw a good fit recently. 
>>>> However, I'm a little bit unsure about this situation. I have some Thrift 
>>>> objects that I'd like to be able to easily unpack into maps, so I created 
>>>> a 
>>>> protocol
>>>>
>>>> (defprotocol Unpackable
>>>>   (unpack [x]))
>>>>
>>>> Thrift has two main data types - structs and unions that need to be 
>>>> handled differently. Structs always implement the interface TBase. Unions 
>>>> extend the abstract class TUnion which in turn implements the interface 
>>>> TBase. So I'm extending my protocol to these types like this:
>>>>
>>>> (extend-protocol IUnpackable
>>>>   TUnion
>>>>   (unpack [x] (unpack-union x))
>>>>
>>>>   TBase
>>>>   (unpack [x] (unpack-struct x (get-meta-data (class x)))))
>>>>
>>>> It all seems to work correctly, but I'm a little unsure that it is 
>>>> guaranteed to work especially in the case of a union. Since a union 
>>>> extends 
>>>> TUnion, but also implements TBase will a call to (unpack the-union) do the 
>>>> right thing (go to unpack-union instead of unpack-struct) every time?
>>>>
>>>> Thanks.
>>>>
>>>  -- 
>> -- 
>> You received this message because you are subscribed to the Google
>> Groups "Clojure" group.
>> To post to this group, send email to clo...@googlegroups.com<javascript:>
>> Note that posts from new members are moderated - please be patient with 
>> your first post.
>> To unsubscribe from this group, send email to
>> clojure+u...@googlegroups.com <javascript:>
>> For more options, visit this group at
>> http://groups.google.com/group/clojure?hl=en
>> --- 
>> You received this message because you are subscribed to the Google Groups 
>> "Clojure" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to clojure+u...@googlegroups.com <javascript:>.
>> For more options, visit https://groups.google.com/groups/opt_out.
>>  
>>  
>>
>
>

-- 
-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to