clojure - “ISA”是怎样的?基于多方法而不是 instanceof 的语法糖?
问题描述
我从clojure 网站举个例子。
(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
多方法。
从 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
,但它更灵活、更简洁。
推荐阅读
- groovy - 使用 Gradle 和 Groovy 设置 GORM
- javascript - CKEditor 返回 [object Object]
- autodesk-forge - 模型衍生能从BIM中获取所有信息吗?
- ios - Xcode 不更新情节提要中的 UI
- python-3.x - InvalidArgumentError(参见上面的回溯):reshape 的输入是具有 35000 个值的张量,但请求的形状需要 7500 的倍数
- git - 使用 ssh 将 codecommit 存储库克隆到 Codebuild 时遇到问题
- javascript - 如何使用带有 Phaser 框架的 Facebook 即时游戏 SDK 向朋友发送邀请
- keras - 添加层停止学习 Keras
- reactjs - Apache 2.4 + React Router 4 总是路由到我的 404 页面组件
- image - 带有 PNG 的 SVG 在 Safari/WebKit 浏览器上看起来很模糊