deriveで階層の設定。::rectは::shapeの子。階層を設定するキーワードは名前空間付きじゃないといけない。
(derive ::rect ::shape)
;=> nil
parents、ancestors、descendants、isa?で階層が設定されていることを確認できる。
(parents ::rect)
;=> #{:user/shape}
mutimethodを定義。
methodのマッチングは=じゃなくてisa?が使われるので階層を設定したキーワードで直接ディスパッチ。
(defmulti bar (fn [x] x))
;=> #'user/bar
(defmethod bar ::shape [x] "shape!")
;=> #<MultiFn clojure.lang.MultiFn@6061b355>
::shapeしか定義していないので ::rect でも ::shape にマッチ。
(bar ::shape)
;=> "shape!"
(bar ::rect)
;=> "shape!"
::rectにも定義するとそっちが呼ばれる。
(defmethod bar ::rect [x] "rect!")
;=> #<MultiFn clojure.lang.MultiFn@6061b355>
(bar ::rect)
;=> "rect!"
ClojureScriptでも大丈夫だった。