2012-09-22 14 views
5

Dato un insieme, mappa e vettore in Clojure implementare sia IPersistentCollection e IFN, come fa Clojure decidere quale implementazione di SayHi da utilizzare:Risoluzione di chiamata protocollo Clojure quando classe implementa diverse interfacce

(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 

risposta

5

protocollo spedizione è fatta sul tipo del primo argomento della funzione. Quando più implementazioni corrispondono al tipo del primo argomento, viene scelta l'implementazione più specifica. Questo è il motivo per cui la chiamata (hi #{}) risolve l'implementazione dell'insieme e non la raccolta o le implementazioni fn anche se un insieme (#{}) implementa entrambi.

La funzione find-protocol-impl nel clojure-deftype.clj sembra gestire il protocollo di attuare la risoluzione oggetto:

(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

può puntare al codice sorgente clojure in cui questo è fatto? Non sono stato in grado di trovarlo – DanLebrero

+1

@dAni ha aggiornato la risposta –

Problemi correlati