这是一个过于简单的示例:
我可以封装一个实现细节,例如使用一个原子作为计数器:
(defn make-counter
([] (make-counter 0))
([init-val]
(let [c (atom init-val)]
{:get (fn [] @c)
:++ (fn [] (swap! c inc))})))
但这意味着我需要重新定义所有内容以添加功能(无继承):
(defn make-bi-counter
([] (make-bi-counter 0))
([init-val]
(let [c (atom init-val)]
{:get (fn [] @c)
:++ (fn [] (swap! c inc))
:-- (fn [] (swap! c dec))})))
而如果可以只扩展一个功能:
(assoc c :-- (env (:++ c) (fn [] (swap! c dec))))
(def c (make-counter))
(def b (make-bi-counter))
user=> ((:-- b))
-1
user=> ((:-- b))
-2
user=> ((:get b))
-2
或者我可以只暴露原子并拥有独立的功能:
(defn -- [a] (swap! a dec))
(def a (atom 0))
(-- a)
看来最好的选择是放弃封装,如果“继承”(或更准确地说:扩展)是可取的。