Peter Marklund

Peter Marklund's Home

Fri Jul 24 2015 06:16:55 GMT+0000 (Coordinated Universal Time)

Using Clojure Multimethods for Polymorphism and Inheritance

It's fascinating how simple and powerful the multimethod feature in Clojure is. It provides a way to support polymorphism and inheritance that we are used to from object oriented languages:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; BASE CLASS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; public class ContentItem {
; public String foobar() {
; return "content_item";
; }
; }
(defn model-type-dispatch [item]
(keyword (str "model/" (:type item))))
(defmulti foobar model-type-dispatch)
(defmethod foobar :model/content_item [item]
"content_item")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; CHILD CLASS - OVERRIDES METOHD
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; public class Chef extends ContentItem {
; public String foobar() {
; return "chef";
; }
; }
(derive :model/chef :model/content_item)
(defmethod foobar :model/chef [item]
"chef")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; CHILD CLASS - WITHOUT OVERRIDE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; public class Source extends ContentItem {
; }
(derive :model/source :model/content_item)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; MAIN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; public static void main(String[] args) {
; System.out.println(new ContentItem().foobar());
; System.out.println(new Chef().foobar());
; System.out.println(new Source().foobar());
; }
(foobar {:type "content_item"}) ; => content_item
(foobar {:type "chef"}) ; => chef
(foobar {:type "source"}) ; => content_item
(isa? :model/chef :model/content_item) ; => true
(isa? :model/source :model/content_item) ; => true