扩展库提供的协议,而不会影响其他用户

时间:2012-10-17 17:34:17

标签: clojure

我正在使用第三方库(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))))

1 个答案:

答案 0 :(得分:1)

经过一番思考后,我看到了两个基本的方法(其中一个是我从你那里得到的):

动态绑定(正如您现在所做的那样):

有些人抱怨说动态约束对大多数人来说都是有用的; “什么?只有从那里打电话才会这样?”虽然我个人并不认为这是一件坏事(某些人)。在这种情况下,它非常符合您的愿望,只要您有一个点,您决定是否需要关键字字符串,这应该有效。如果你添加一个更改它们的第二个点和一个穿过两个井的代码路径...你自己。但是,嘿,工作代码有它的优点。

继承:

good'ol java风格或使用clojure的add-hoc heirarchies你可以扩展你传递的对象类型为keywordized-string-widgewhatzit,扩展widgewhatzit和为你的特定子类添加一个新的处理程序。这仅适用于某些情况,并在设计的其余部分强制使用不同的对象样式。一些聪明的人也会争辩说它仍然遵循最令人惊讶的原则,因为当通过另一个代码路径调用时,对象的类型将是不同的。

<小时/> 我个人会选择你现有的解决方案,除非你可以改变你的整个程序使用关键字而不是字符串(这当然是我的第一个(可能有争议的)选择)