我是 Clojure 新手,正在寻找一些关于何时使用协议以及何时使用多方法的具体示例。我知道协议通常旨在创建类型层次结构和典型的 OOP 事物,它们是在多方法之后添加到语言中的,并且协议通常具有更好的性能,所以我的问题是:
协议是否旨在取代多方法?如果没有,你能给我一个例子,我会使用多方法而不是协议吗?
我是 Clojure 新手,正在寻找一些关于何时使用协议以及何时使用多方法的具体示例。我知道协议通常旨在创建类型层次结构和典型的 OOP 事物,它们是在多方法之后添加到语言中的,并且协议通常具有更好的性能,所以我的问题是:
协议是否旨在取代多方法?如果没有,你能给我一个例子,我会使用多方法而不是协议吗?
协议和多方法是互补的,适用于略有不同的用例。
一般来说,我的建议是使用协议,除非您有需要多方法的特定情况。
您可能需要多种方法的情况如下:
(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!")))
请注意,由于以下两个原因,您不能在此处使用协议:
多方法更强大,更昂贵,
在足够的情况下使用协议,但如果您需要根据从火星看到的月相进行调度,那么多方法是您的最佳选择。
协议的存在是为了让简单的东西保持简单,并为 clojure 提供一种生成与等效 java 相同的字节码的方法。似乎大多数人大部分时间都使用协议。当我需要调度多个参数时,我会使用多方法,尽管我不得不承认这只出现过一次,而且完整isa
的层次结构使用得更少(我)。所以简而言之,在需要时使用 Multimethods
在我的经验中,最好的例子是在一开始,在core.clj
正如 Arthur 所提到的,多方法更强大且更昂贵。事实上,协议可以被认为是多种方法的一个特例,其中 dispatch 函数是 class
. 当然,情况并非如此,因为协议不止于此。
如果您需要调度除第一个参数的类以外的其他内容,则需要使用多方法或重新设计。对类型进行调度是协议的一个很好的用例。
当您不需要类层次结构时,我喜欢多方法。例如,如果您有一个媒体数据库并且您的记录是这样的,{: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 世界应该留下的祸根。多方法只是函数,对我来说感觉更像是clojuresque。