clojure.core/extend¶
Implementations of protocol methods can be provided using the extend construct:
(extend AType AProtocol {:foo an-existing-fn :bar (fn [a b] ...) :baz (fn ([a]...) ([a b] ...)...)} BProtocol {...} ...)
extend takes a type/class (or interface, see below), and one or more protocol + method map pairs. It will extend the polymorphism of the protocol's methods to call the supplied methods when an AType is provided as the first argument.
Method maps are maps of the keyword-ized method names to ordinary fns. This facilitates easy reuse of existing fns and fn maps, for code reuse/mixins without derivation or composition. You can extend an interface to a protocol. This is primarily to facilitate interop with the host (e.g. Java) but opens the door to incidental multiple inheritance of implementation since a class can inherit from more than one interface, both of which extend the protocol. It is TBD how to specify which impl to use. You can extend a protocol on nil.
If you are supplying the definitions explicitly (i.e. not reusing exsting functions or mixin maps), you may find it more convenient to use the extend-type or extend-protocol macros.
Note that multiple independent extend clauses can exist for the same type, not all protocols need be defined in a single extend call.
See also: extends?, satisfies?, extenders
Examples¶
Note by nethopper¶
The type being extended must be imported even if it is a Clojure type (e.g. a record). So the following works:
(ns com.example-ns.a
(:import (com.example_ns.b Foo))) ;; <-- import
(defprotocol IBar
(bar [_]))
(extend Foo
IBar
{:bar identity})
But this fails to compile:
(ns com.example-ns.a
(:require [com.example-ns.b :refer [Foo]])) ;; <-- require
(defprotocol IBar
(bar [_]))
(extend Foo
IBar
{:bar identity})
See defrecord example.
See also¶
- clojure.core/satisfies? (0)
- clojure.core/extends?
- clojure.core/extenders
- clojure.core/extend-type
- clojure.core/extend-protocol
Content from the matching ClojureDocs page, with authors credited on each contribution.