2012-10-17 24 views
5

我正在使用第三方庫(clj-msgpack),並希望擴展該庫也提供處理程序的類型的協議。擴展庫提供的協議,而不會影響其他用戶

就其本身而言,這很簡單 - 但是有什麼辦法可以做到這一點,而不會影響在同一個JVM中運行的這個庫的其他用戶嗎?類似於動態變量綁定(僅在棧上的給定點下生效)將是理想的。

目前,我正在做無條件覆蓋,但使用動態變量來啓用我的修改行爲;然而,這感覺像猴子修補我的舒適太像。

對於好奇的(承認憎惡)我把到位如下:

(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)))) 
+0

叉,添加你需要的功能,並提交拉請求; ^) – noahlz

+0

@noahz我已經提交了一個包含代碼的票。無論上游是否認爲此功能_desirable_是一個非常值得懷疑的事情 - 但我不確定如果我是他們,我會接受它。 –

+0

我做了這個評論tounge-cheek(出於你提到的原因),但另一方面,API應該是「開放的擴展,關閉修改」。 – noahlz

回答

1

經過一番思考我看到兩個基本approches(其中一個我從你):

動態綁定(如你現在這樣做):

有人抱怨說動態綁定對大多數提供者的主體有效; 「只有當從那裏打電話時,這種方式表現如何?」。雖然我個人並不認爲這是一件壞事(有些人)會這樣做。在這種情況下,它完全符合你的願望,只要你有一個決定你是否想要關鍵字化的字符串,這應該工作。如果你添加第二個改變他們的點,並且有一個代碼路徑跨越兩個地方......你自己做的。但是,嘿,工作代碼有它的優點。

繼承:

good'ol Java的方式或使用Clojure的附加特殊heirarchies你可以擴展你身邊掠過被keywordized串-widgewhatzit擴展widgewhatzit和添加一個新的處理程序對象的類型您的具體子類。這隻適用於某些情況,並在設計的其餘部分強制使用不同的對象風格。一些聰明人也會爭辯說,它仍然遵循最令人驚訝的原則,因爲當通過另一條代碼路徑調用時,對象的類型將會有所不同。


個人而言,我會與您現有的解決方案去,除非你可以改變你的整個程序中使用關鍵字,而不是字符串(當然,這將是我的第一個(可能有爭議)選擇)

+0

我不能做基於子類的協議實現方法,因爲正在處理的對象是由庫本身生成的(實際上是由庫_it_使用)。這將遠遠超出我的偏好,因爲它完全取決於其他用戶。 –

+0

...順便說一下,我不喜歡當前方法的主要原因是它修改了庫代碼。是的,新行爲應該被動態綁定切換...但是如果上行調整了原始代碼路徑,並且我沒有將該功能應用於我的重寫版本,則給定Clojure環境中的庫的_all_用戶將失去上游改變,不僅僅是我自己的代碼。我已經在Ruby和Python世界中用猴子補丁燒了足夠多,因此非常非常謹慎地在此認可它。 –

+0

好吧,現在你發佈了它,有人會按照你的例子;-)你正在進入另一個圖書館,並擺弄它的位,所以可能會有一些限制,如何得到乾淨: -/ –