我正在使用第三方库(clj-msgpack),并希望为库提供处理程序的类型扩展协议.
就其本身而言,这很简单 - 但是有没有办法做到这一点,这不会影响在同一个JVM中运行的这个库的其他用户?类似于动态var绑定的东西(仅在堆栈上的给定点下生效)将是理想的.
目前,我正在进行无条件覆盖,但使用动态var来启用我修改后的行为; 然而,这感觉太像猴子修补我的舒适.
对于好奇,我承认的(承认憎恶)如下:
(in-ns 'clj-msgpack.core)
(def ^:dynamic *keywordize-strings*
"Assume that any string starting with a colon should be unpacked to a keyword"
false)
(extend-protocol Unwrapable
RawValue
(unwrap [o]
(let [v (.getString o)]
(if (and *keywordize-strings* (.startsWith v ":"))
(keyword (.substring v 1))
v))))
Run Code Online (Sandbox Code Playgroud)
经过一番思考,我看到了两种基本方法(其中之一是我从你那里得到的):
动态绑定(正如您现在所做的那样):
有些人抱怨动态绑定是最令人惊讶的原则。“什么?只有从那里调用时才会这样?”。虽然我个人并不认为这是一件坏事,但有些人却这么认为。在这种情况下,它完全符合您的愿望,只要您有一点决定是否需要关键字化字符串,这应该可行。如果您添加第二个点来将它们更改回来,以及一个交叉两者的代码路径......您自己就可以了。但是,嘿,工作代码有它的优点。
遗产:
好的ol java风格或使用clojure的附加层次结构,您可以将传递的对象类型扩展为keywordized-string-widgewhatzit,它扩展了widgewhatzit并为您的特定子类添加新的处理程序。这仅在某些情况下有效,并在设计的其余部分强制使用不同的对象样式。一些聪明的人还会争辩说,它仍然遵循最令人惊讶的原则,因为当通过另一个代码路径调用时,对象的类型会有所不同。