【发布时间】:2011-12-25 14:28:05
【问题描述】:
我是 Clojure 新手,正在寻找一些关于何时使用协议以及何时使用多方法的具体示例。我知道协议通常旨在创建类型层次结构和典型的 OOP 事物,它们是在多方法之后添加到语言中的,并且协议通常具有更好的性能,所以我的问题是:
协议是否旨在取代多方法?如果没有,你能给我举个例子,我会使用多方法而不是协议吗?
【问题讨论】:
标签: clojure multimethod
我是 Clojure 新手,正在寻找一些关于何时使用协议以及何时使用多方法的具体示例。我知道协议通常旨在创建类型层次结构和典型的 OOP 事物,它们是在多方法之后添加到语言中的,并且协议通常具有更好的性能,所以我的问题是:
协议是否旨在取代多方法?如果没有,你能给我举个例子,我会使用多方法而不是协议吗?
【问题讨论】:
标签: clojure multimethod
协议和多方法是互补的,适用于略有不同的用例。
一般来说,我的建议是使用协议,除非您有需要多种方法的特定情况。
您可能需要多种方法的情况如下:
(defn balance-available? [amount balance] (> balance amount))
(defmulti withdraw balance-available?)
(defmethod withdraw true [amount balance]
(- balance amount))
(defmethod withdraw false [amount balance]
(throw (Error. "Insufficient balance available!")))
请注意,由于以下两个原因,您不能在此处使用协议:
【讨论】:
当您不需要类层次结构时,我喜欢多方法。例如,如果您有一个媒体数据库并且您的记录类似于{:media-type :video, :bytes ...},那么您可以使用多种方法
(defmulti make-grayscale :media-type)
然后你可以制作各种
; in video.clj
(defmethod make-grayscale :video [record]
(ffmpeg ... (:bytes record))
; in photo.clj
(defmethod make-grayscale :photo [record]
(imagemagick ... (:bytes record))
这样您就可以避免使用中心 cond 表达式,从而获得类的模块化。但是您不必经历所有那些“包装类层次结构”样板,对我来说这是一个应该留给 Java 世界的祸根。 Multimethods 只是函数,对我来说感觉更像是clojuresque。
【讨论】:
多方法更强大,也更昂贵,
在足够的情况下使用协议,但如果您需要根据从火星上看到的月相进行调度,那么多方法是您的最佳选择。
协议的存在是为了让简单的东西保持简单,并为 clojure 提供一种方法来生成与等效的 java 几乎相同的字节码。似乎大多数人大部分时间都使用协议。当我需要调度多个参数时,我会使用多方法,尽管我不得不承认这只出现过一次,而且完整的isa 层次结构使用得更少(我)。所以简而言之在需要时使用多方法
根据我的经验,最好的例子是一开始,core.clj
【讨论】:
正如 Arthur 所提到的,多方法更强大且更昂贵。事实上,协议可以被认为是多种方法的一个特例,其中调度函数是class。当然,实际情况并非如此,因为协议不止于此。
如果您需要调度除第一个参数的类以外的其他内容,则需要使用多方法或重新设计。对类型进行调度是协议的一个很好的用例。
【讨论】: