我是Clojure的新手,正在寻找一些具体的例子来说明何时使用协议和何时使用多方法。我知道协议通常用于创建类型层次结构和典型的面向对象编程,它们在多方法之后添加到语言中,并且协议通常具有更好的性能,因此我的问题是:
协议是否意味着取代多方法?如果不是,您能给我一个使用多方法而不是协议的例子吗?
我是Clojure的新手,正在寻找一些具体的例子来说明何时使用协议和何时使用多方法。我知道协议通常用于创建类型层次结构和典型的面向对象编程,它们在多方法之后添加到语言中,并且协议通常具有更好的性能,因此我的问题是:
协议是否意味着取代多方法?如果不是,您能给我一个使用多方法而不是协议的例子吗?
协议和多方法是互补的,旨在解决略有不同的使用情况。
一般来说,我的建议是除非您有具体需要使用多方法,否则请使用协议。
您可能需要使用多方法的情况如下所示:
(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 层次结构很少被使用(也很少被我使用)。因此,在需要时请使用多态方法
在我的经验中,最好的例子就在开始,即core.clj 中。
class
。当然,这并不完全正确,因为协议不仅仅是这样。在不需要类层次结构的情况下,我喜欢使用多态(multimethods)。例如,如果您拥有媒体数据库,且记录如下所示:{: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世界应该留下的祸根。多方法只是函数,感觉更像Clojure。