2017-02-24 59 views
3

我正在編寫一些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中執行第二個協議代碼莫名其妙干涉第一個。

最終我想爲這些類的方法編寫多態封裝函數,但我不知道如何儘可能簡單和儘可能乾淨地完成此操作。請指教...

+1

好像你必須分別處理RealDistribution和IntegerDistribution,因爲它們在apache commons-math中沒有共同的祖先。我不知道這是如何製作clojure,但基本的想法是,這兩個應該是分開的 – borowis

+0

我確實對待他們分開。但是,當我擴展RealDistribution後擴展IntegerDistribution時,它會以某種方式干擾RealDistribution並導致顯示的錯誤。 – Lindon

回答

1

你寫的應該沒問題,但如果有任何實現這兩個接口的類都會遇到麻煩。

至於你爲什麼說它不適合你:你確定嗎?IntegerDistribution其實沒有density參數,並且您的錯誤消息顯示您實際上正在定義一個名爲univariate-integer而不是density-eval的協議,因此我想知道在嘗試簡化並隔離堆棧溢出問題時是否發生了錯誤。

+0

你是對的,我試圖創建一個最小的例子,我犯了一個錯誤。但問題依然存在。我將更新帖子,更具體的細節 – Lindon

+0

更新了原始帖子更多細節 – Lindon