2012-09-22 3 views
5

einen Satz, Karte und Vektor in Clojure implementieren sowohl IPersistentCollection und IFN- gegeben, wie funktioniert Clojure entscheiden, welche Implementierung von SayHi zu verwenden:Auflösung von Call Clojure-Protokoll, wenn Klasse implementiert mehrere Schnittstellen

(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 

Antwort

5

Protokoll Versand erfolgt auf den Typ des ersten Arguments der Funktion. Wenn mehrere Implementierungen dem Typ des ersten Arguments entsprechen, wird die spezifischste Implementierung ausgewählt. Deshalb löst der Aufruf (hi #{}) auf die set-Implementierung und nicht die Auflistung oder Fn-Implementierungen auf, obwohl eine Gruppe (#{}) beide implementiert.

Die find-protocol-impl Funktion im clojure-deftype.clj scheint das Protokoll zur Umsetzung Objektauflösung zu handhaben:

(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

Können Sie mit dem clojure Quellcode zeigen, wo dies geschehen ist? Ich konnte es nicht finden – DanLebrero

+1

@dAni aktualisierte die Antwort –

Verwandte Themen