In Clojure, if you want a basic OOP behavior without killing yourself to fully implement Java classes and interfaces in Clojure, the preferred technique is to use records. Sometimes implementing protocols in records suits your needs, mostly due to speed of code execution. However, if you want polymorphism with your records, then multimethods are where it’s at.
Admittedly, multimethods are very flexible, so the technique I’ll show you is one of many techniques you could use. The basic pattern I use for inheritance with records, is to use the derive command with keywords that are kept as a value in the record. For example,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
(defrecord food [ ^Keyword type ^String name ^String color ^boolean yummy ]) (defn construct-food [name color yummy] (->food ::food name color yummy)) (derive ::fruit ::food) (defrecord fruit [ ^Keyword type ^String name ^String color ^boolean yummy ^boolean needs-peeling ]) (defn construct-fruit [name color yummy needs-peeling] (->fruit ::fruit name color yummy needs-peeling)) |
type is used to track isa relationships of ::food and ::fruit . derive is used to set ::food as the parent of ::fruit . Notice the use of custom constructors to set default values for type in the records.