簡體   English   中英

如何在Clojure中使用defrecord擴展一個Java class?

[英]How to use defrecord in Clojure to extend a Java class?

根據我的研究,擴展 Java class 的方法基本上是使用命名空間中的 gen-class 或代理。 但是看Clojure選型流程圖,好像建議我可以用record擴展一個Java class:

  1. 該類型是否需要擴展 Java class 或實現任何接口? 是的
  2. 您需要命名類型還是僅需要匿名類型的實例? 命名類型
  3. 您是否需要能夠從 Java 靜態引用 class?
  4. 您的 class 是否正在對域值進行建模 - 從而受益於類似 hasmap 的功能和語義學? 是的

使用解凍記錄

所以問題是......如何?

例如(從這個):

public final class Second extends Struct {
    public final Signed32 a_number = new Signed32();
    public Second(final Runtime runtime) {
        super(runtime);
    }
}

public final class Top extends Struct {              
    public final Second second = inner(new Second(getRuntime()));  
    public final Second[] seconds = array(new Second[5]);
    public final Signed32 another_number = new Signed32();
    public final Signed32[] more_numbers = array(new Signed32[5]);
    public Top(final Runtime runtime) {
        super(runtime);
    }
}

我...

(defrecord Second)
(extend jnr.ffi.Struct
        Second)

我認為流程圖是錯誤的。 檢查Clojure - 數據類型:deftype、defrecord 和 reify文檔我們可以看到:

  • deftype/defrecord 可以實現一個或多個協議和/或接口

沒有提到擴展現有的 class。事實上,查看defrecord本身的文檔沒有提到擴展現有的類,除了Object作為特例。

抱歉, proxygen-class似乎是您唯一的選擇。

為什么需要命名類型? 如果,如您所說,您不需要從 Java 靜態引用它,我看不出有任何特別的理由來命名該類型。 如果你正確回答了這個問題,它會引導你到proxy 您的問題是您選擇了不一致的答案:您說您需要一個已命名的 class,但對於您可能需要一個的任何原因都沒有回答是。 流程圖考慮的原因是 Java 代碼可能希望通過名稱引用您的代碼,在這種情況下gen-class 但是,一方面說您必須擴展 Java class,另一方面說您的新類型將是一個簡單的數據載體,為域值建模是沒有意義的。 Clojure 記錄在這方面做得很好,但是擁有一個來自 Java 的令人討厭的可變基礎 class 並不能構成一個好的域 object。

也就是說,如果您對“建模域類型”回答“否”,它會引導您使用deftype ,它也不能擴展 class。我認為它允許您逃離“互操作區”是一個錯誤如果你想擴展一個 class: 最好將接口和子類分開,但流程圖只能這么大。

FWIW 對原始流程圖帖子的評論包括您的問題和作者的回答,回應了我使用proxy的建議以及流程圖已經足夠大的問題:

第一個決定並不僅僅表明您需要擴展 class — 它包括實現接口。 所以,那里有點模棱兩可。 當然,你在 gen-class-land 那里,但我認為將事情分解更多以消除歧義會使流程圖更大一些。

FWIW,我個人會在那里放棄命名類型要求,使用代理,然后只定義 (class (create-proxy-instance …)) 的結果? 檢查等(假設這就是您需要命名類型的原因)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM