2013-02-23 91 views
10

在Clojure中,我想要一个协议,其中一些方法具有默认实现,并且一些具有自定义实现。前者是指后者的配置。这里是一个例子:Clojure - 自定义实现的混合协议默认实现

(defprotocol Saving 
    (save [this] "saves to mongodb") 
    (collection-name [this] "must return a string representing the associated MongoDB collection")) 

;Default implementation 

(extend-type Object 
    Saving 
    ; the `save` method is common for all, so it is actually implemened here 
    (save [this] (mc/insert (collection-name [this]) this)) 
    ; this method is custom to every other type 
    (collection-name [this] "no_collection")) 

;Particular implementations 

(defrecord User 
    [login password] 
    Saving 
    (collection-name [this] "users")) 

(defrecord NewsItem 
    [text date] 
    Saving 
    (collection-name [this] "news_items")) 

但是,它不会这样工作。即使在UserNewsItemNewsItem上调用collection-nameNewsItem实例返回正确的收集字符串,但在其上调用save会导致AbstractMethodError。我如何用Clojure实现这个微不足道的OO形目标?

回答

12

请保存功能的普通函数:

(defn save [obj] (mc/insert (collection-name obj) obj)) 

协议应该只有collection-name

(defprotocol Saving 
    (collection-name [this] "must return a string representing the associated MongoDB collection")) 

然后想要被“拯救”每个对象都可以实现此协议。

记住:OO风格常常掩盖了明显简单的事情:)

+0

我有一个类似的问题,要做到这一点:我想一个抽象的协议方法和一个默认的别名,它具有相同的功能。别名只会调用抽象方法。别名的原因是提供Java调用者友好名称。我可以做到这一点吗? – Midiparse 2017-08-25 13:45:45