Created
August 18, 2017 16:36
-
-
Save david-mcneil/f6574afd0b3e4260dd70d65455c09833 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; 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 | |
[_] | |
[_ s]) | |
(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)) | |
([doggable s] | |
(str (bark doggable) " " s))) | |
: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)" | |
(speak fido "hi") | |
;; => "arf (collie) hi" | |
;; 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))) | |
([trained-dog s] | |
(str (:word trained-dog) " " s))) | |
: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" | |
(speak rex "hi") | |
;; => "hello hi" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment