Skip to content

Instantly share code, notes, and snippets.

@david-mcneil
Created November 4, 2010 01:05
Show Gist options
  • Save david-mcneil/661983 to your computer and use it in GitHub Desktop.
Save david-mcneil/661983 to your computer and use it in GitHub Desktop.
Demonstration of implementation "inheritance" in clojure
;; Define a "base type" of Dog
(defrecord Dog [breed])
;; Define a "sub type" of TrainedDog
(defrecord TrainedDog [dog word])
;; The interface that both Dog and TrainedDog will implement
(defprotocol Talker
(bark [_])
(speak [_])
(to-dog [_]))
;; The base behavior that will be used for Dogs and TrainedDogs
(def base-behavior {:bark (fn [doggable]
(str "arf (" (:breed (to-dog doggable)) ")"))
:speak (fn [doggable]
(bark doggable))
:to-dog (fn [dog] dog)})
;; Use the base behavior as the implmentation of the Dog Talker behavior.
(extend Dog
Talker
base-behavior)
(def fido (Dog. "collie"))
(bark fido)
;; => "arf (collie)"
(speak fido)
;; => "arf (collie)"
;; For the TrainedDog, start with the base-behavior but "override" two
;; of the functions with alternate behavior.
(extend TrainedDog
Talker
(merge base-behavior
{:speak (fn [trained-dog] (str (:word trained-dog)))
:to-dog (fn [trained-dog] (:dog trained-dog))}))
(def rex (TrainedDog. (Dog. "yorkie") "hello"))
;; TrainedDogs use the 'bark' implementation from the base-behavior
(bark rex)
;; => "arf (yorkie)"
;; TrainedDogs use their own 'speak' implementation
(speak rex)
;; => "hello"
@collinalexbell
Copy link

collinalexbell commented Aug 18, 2016

The to-dog workarounds seems a bit odd to me. I guess since there are no explicit constructors it is necessary. I know one could combine defn's and defmulti's to create a multiple arity constructor dispatched by argument type and then keep the base data structure in the child class the same as the parent class so that the base methods still work correctly without to-dog while still having the power to construct the child class using an instance of the base class.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment