2012-09-22 9 views
5

Dado un conjunto, un mapa y el vector en Clojure implementar tanto IPersistentCollection e IFN, ¿cómo decidir Clojure cuales la implementación de SayHi de usar:Resolución de Clojure llamada de protocolo cuando la clase implementa varias interfaces

(defprotocol SayHi 
    (hi [this])) 

(extend-protocol SayHi 
    clojure.lang.IPersistentCollection 
    (hi [_] (println "Hi from collection")) 
    clojure.lang.IFn 
    (hi [_] (println "Hi from Fn!")) 
    clojure.lang.IPersistentSet 
    (hi [_] (println "Hi from set!"))) 

(hi #{}) 
Hi from set! 
(hi []) 
Hi from collection 

Respuesta

5

despacho Protocolo se hace en el tipo del primer argumento de la función. Cuando múltiples implementaciones coinciden con el tipo del primer argumento, se elige la implementación más específica. Es por eso que la llamada (hi #{}) se resuelve en la implementación del conjunto y no en la colección o las implementaciones fn aunque un conjunto (#{}) implemente ambas.

La función find-protocol-impl en el clojure-deftype.clj parece manejar el protocolo de aplicación de la resolución objeto:

(defn find-protocol-impl [protocol x] 
    (if (instance? (:on-interface protocol) x) 
    x 
    (let [c (class x) 
      impl #(get (:impls protocol) %)] 
     (or (impl c) 
      (and c (or (first (remove nil? (map impl (butlast (super-chain c))))) 
        (when-let [t (reduce1 pref (filter impl (disj (supers c) Object)))] 
         (impl t)) 
        (impl Object))))))) 
+1

Puede señalar al código fuente clojure donde se hace esto? No he podido encontrarlo – DanLebrero

+1

@dAni actualizó la respuesta –

Cuestiones relacionadas