Ottima domanda. Ecco una risposta basata su uno simile che ho dato su StackOverflow.
Come al solito, c'è un bel modo di fare cose in Clojure - ecco come implementare il tuo semplice sistema OO dinamico (includendo ereditarietà, polimorfismo e incapsulamento) in 10 linee di Clojure.
L'idea: puoi mettere le funzioni nelle normali mappe o record Clojure se vuoi, creando una struttura simile a OO. Puoi quindi usarlo in uno stile "prototipo".
; define a prototype instance to serve as your "class"
; use this to define your methods, plus any default values
(def person-class
{:get-full-name
(fn [this] (str (:first-name this) " " (:last-name this)))})
; define an instance by merging member variables into the class
(def john
(merge person-class
{:first-name "John" :last-name "Smith"}))
; macro for calling a method - don't really need it but makes code cleaner
(defmacro call [this method & xs]
'(let [this# ~this] ((~method this#) this# ~@xs)))
; call the "method"
(call john :get-full-name)
=> "John Smith"
; added bonus - inheritance for free!
(def mary (merge john {:first-name "Mary"}))
(call mary :get-full-name)
=> "Mary Smith"