defprotocol defines a polymorphic interface whose functions dispatch on the type of their first argument. It combines a native Java interface with Clojure functions and an extension table, allowing behavior to vary independently of Java class inheritance. section 15.0 section 15.8
(defprotocol MyProtocol ; #1
(method1 [this])
(method2 [this]))
(pprint (vec (.getDeclaredMethods user.MyProtocol))) ; #2
;; [#object[Method "public abstract java.lang.Object user.MyProtocol.method1()"]
;; #object[Method "public abstract java.lang.Object user.MyProtocol.method2()"]]
(pprint MyProtocol) ; #3
;; {:on user.MyProtocol,
;; :on-interface user.MyProtocol,
;; :sigs
;; {:method1 {:name method1, :arglists ([this]), :doc nil},
;; :method2 {:name method2, :arglists ([this]), :doc nil}},
;; :var #'user/MyProtocol,
;; :method-map {:method1 :method1, :method2 :method2},
;; :method-builders
;; {#'user/method2 #object["user$eval1675$fn__1676@6f9e2121"],
;; #'user/method1 #object["user$eval1675$fn__1687@78d76411"]}}
(fn? method1) ; #4
;; true
(fn? method2)
;; true
Inspecting a protocol reveals its generated Java interface, method signatures, metadata, dispatch functions, and method builders. section 15.8
Declare, implement, and extend a protocol
(defprotocol MyProtocol (method1 [this]) (method2 [this])) (deftype MyProtocolImpl [] MyProtocol (method1 [this] "direct implementation")) (method1 (MyProtocolImpl.)) ;; "direct implementation" (extend java.lang.String MyProtocol {:method1 #(.toUpperCase %)}) (method1 "arg") ;; "ARG" A type can implement the protocol directly through deftype, defrecord, proxy, or reify, or an existing class can be extended with extend, extend-type, or related variants. Extending a type that already implements the protocol raises IllegalArgumentException. section 15.8
Dispatch and implementation details:
- Each declared method becomes a Clojure function that selects an implementation from the actual class, metadata when enabled, or the extension table. section 15.8
- Add :extend-via-metadata true to permit instance-specific implementations supplied through metadata. section 15.8
- Direct interface implementation is reported as slightly faster than later extension in the supplied benchmark, though both approaches support the same polymorphic design. section 15.8
