我正在編寫一些Clojure中的代碼,它很大程度上依賴於Apache Commons Math3庫中的某些功能。我從來沒有寫過任何Java代碼,並試圖想出一個優雅的解決方案來創建我經常使用的clojure包裝器。希望我能夠交流我正在嘗試做的事情,儘管不是真正的OOP或Java專家。我將用一個具體的簡單例子來描述挑戰Clojure中的多態性實現接口的Java類 - 包裝器編寫
一般來說,我有一個java類的集合,它們都從給定的接口繼承了一些方法。舉一個具體的例子,考慮一下distributions包。有3個接口,其中之一是RealDistribution。繼承RealDistribution接口的類可以訪問某些方法,如「密度」。
Clojure中我可以做
(.density (new NormalDistribution 0 1) 2)
(.density (new ExponentialDistribution 1) 2)
的目標是編寫一個多態函數「密度」的調度上的不同分佈,自己的Java類。
我可以寫一個協議,稱之爲密度-EVAL
(defprotocol density-eval
(density [distribution x]))
和擴展各分配手動像
(extend-type NormalDistribution
density-eval
(density [d x] (.density d x)))
但是我需要爲每個配送做到這一點...和那裏有一個他們中的很多...和每個分配的代碼是相同的。
爲了節省時間,我想要做的是擴展一些更一般的東西......比如NormalDistribution的父類型,但我不知道從哪裏去。我現在擁有的是
(extend-type RealDistribution
density-eval
(density [d x] (.density d x)))
RealDistribution是NormalDistribution和ExponentialDistribution實現的接口。而且這個工作......我可以調用(密度y x)實現RealDistribution接口的許多發行版。例如(密度(new NormalDistribution 0 1)0)正常工作。然而,問題在於我爲實現IntegerDistribution接口的類玩同一個遊戲。我定義了一個新的協議
(defprotocol pmf-eval
(pmf [distribution x]))
(extend-type IntegerDistribution
pmf-eval
(pmf [d x] (.probability d x)))
,然後實現了IntegerDistribution接口,我可以做這樣的事情(PMF(新泊松分佈3)2),工程出精品班......但後來我再也無法通話(密度yx)在實現RealDistribution接口的分佈上。我得到的錯誤:
1. Unhandled java.lang.IllegalArgumentException
No implementation of method: :density of protocol:
#'distributions.core/density-eval found for class:
org.apache.commons.math3.distribution.NormalDistribution
當我在repl中執行第二個協議代碼莫名其妙干涉第一個。
最終我想爲這些類的方法編寫多態封裝函數,但我不知道如何儘可能簡單和儘可能乾淨地完成此操作。請指教...
好像你必須分別處理RealDistribution和IntegerDistribution,因爲它們在apache commons-math中沒有共同的祖先。我不知道這是如何製作clojure,但基本的想法是,這兩個應該是分開的 – borowis
我確實對待他們分開。但是,當我擴展RealDistribution後擴展IntegerDistribution時,它會以某種方式干擾RealDistribution並導致顯示的錯誤。 – Lindon