基于 "isa?" 的多方法如何比 instanceof 的语法糖更重要?
How is an "isa?" based multimethod more than syntax sugar for instanceof?
我正在以 clojure site 中的示例为例。
(defmulti foo class)
(defmethod foo ::collection [c] :a-collection)
(defmethod foo String [s] :a-string)
(foo [])
:a-collection
(foo (java.util.HashMap.))
:a-collection
(foo "bar")
:a-string
这个功能很酷。我试图理解为什么这优于(例如)java 中基于 instanceof 的实现的技术原因。在我看来,它在功能上基本等同,语法更好。
public <T> String foo(final T t) {
if (t instanceof Collection) {
return "a-collection";
} else if (t instanceof String) {
return "a-string";
} else {
throw new IllegalArgumentException("Undefined - no available dispatch");
}
}
为什么 multimethods 被认为是基于访问者模式的双重分派的一个很好的替代品,而 instanceof 却不是,因为它们看起来本质上是在做同样的事情?
评论中讨论的好处之一是 defmulti
和 defmethod
可以由不同的用户在不同的文件中完成。一个很好的例子是 Clojure 自己的 print-method
多方法。
From the docs,我们看看如何为我们创建的新记录类型定义自定义 print-method
:
(deftype XYZ [])
; without custom print-method defined:
user=> (prn (XYZ.))
#<XYZ user.XYZ@2670d85b>
; Note, this hooks into the pre-existing `(defmulti print-method ...)`
(defmethod print-method XYZ [v ^java.io.Writer w]
(.write w "<<-XYZ->>"))
; with print-method
user=> (prn (XYZ.))
<<-XYZ->>
因此,虽然它与巨大的 cond
语句有相似之处,但它更灵活、更简洁。
我正在以 clojure site 中的示例为例。
(defmulti foo class)
(defmethod foo ::collection [c] :a-collection)
(defmethod foo String [s] :a-string)
(foo [])
:a-collection
(foo (java.util.HashMap.))
:a-collection
(foo "bar")
:a-string
这个功能很酷。我试图理解为什么这优于(例如)java 中基于 instanceof 的实现的技术原因。在我看来,它在功能上基本等同,语法更好。
public <T> String foo(final T t) {
if (t instanceof Collection) {
return "a-collection";
} else if (t instanceof String) {
return "a-string";
} else {
throw new IllegalArgumentException("Undefined - no available dispatch");
}
}
为什么 multimethods 被认为是基于访问者模式的双重分派的一个很好的替代品,而 instanceof 却不是,因为它们看起来本质上是在做同样的事情?
评论中讨论的好处之一是 defmulti
和 defmethod
可以由不同的用户在不同的文件中完成。一个很好的例子是 Clojure 自己的 print-method
多方法。
From the docs,我们看看如何为我们创建的新记录类型定义自定义 print-method
:
(deftype XYZ [])
; without custom print-method defined:
user=> (prn (XYZ.))
#<XYZ user.XYZ@2670d85b>
; Note, this hooks into the pre-existing `(defmulti print-method ...)`
(defmethod print-method XYZ [v ^java.io.Writer w]
(.write w "<<-XYZ->>"))
; with print-method
user=> (prn (XYZ.))
<<-XYZ->>
因此,虽然它与巨大的 cond
语句有相似之处,但它更灵活、更简洁。