创建一个Protocols和defrecords库,供Java使用

int*_*tar 12 clojure clojure-java-interop clojure-protocol

目前,我有一个完全功能的Clojure库,它是从Java调用的.

我这样做的方式:我有一个文件,它使用gen-class将整个API包装为单个类的静态方法,并以IPersistentVector和IPersistentMap的形式传入和传出数据.

然而,现在,我正在重构库并将功能置于各种协议之后.

我有四个协议,我们称之为A,B,C和D.两个defrecords,X和Y.X和Y都实现协议A,B和C.而Y也实现D.

我需要做些什么才能使这些可用于Java?这些是否自动作为接口和类?或者我仍然必须做相当于gen-class的公开?

如果没有,什么是gen-class:methods子句的等价物,我在哪里定义方法参数的Java类型?

有没有人有一个简单的例子可以让Java的协议和记录可用?

nha*_*nha 6

defprotocol

每个Clojure协议也是具有相同名称和方法的Java接口.如果我从ibm developerworks中获取示例,我们会看到:

(ns com.amalgamated)

(defprotocol Fulfillment
  (invoice [this] "Returns an invoice")
  (manifest [this] "Returns a shipping manifest"))
Run Code Online (Sandbox Code Playgroud)

相当于:

package com.amalgamated;

public interface Fulfillment {
    public Object invoice();
    public Object manifest();
}
Run Code Online (Sandbox Code Playgroud)

Clojure.org也有一些(相当简洁的)信息.

希望参与协议的Java客户端可以通过实现协议生成的接口来最有效地完成此任务.可以使用extend构造提供协议的外部实现(当您希望不在控件中的类或类型参与协议时需要):

(extend AType   AProtocol   
 {:foo an-existing-fn
    :bar (fn [a b] ...)
    :baz (fn ([a]...) ([a b] ...)...)}   BProtocol
    {...} ...)
Run Code Online (Sandbox Code Playgroud)

definterface

如果您的目标是性能,您可以考虑使用definterface,其使用类似于协议.这篇SO帖子还有关于如何使用它的详细信息:

(definterface Foo
  [^int foo [x ^String y]]
  [^void bar [^ints is]])
Run Code Online (Sandbox Code Playgroud)

definterface似乎比协议更快.

defrecord

类似地,records(以及deftypedefinterface)将生成Java类.同样,Clojure.org/datatypes提供了有用的信息(强调我的):

deftype和defrecord使用一组给定字段动态生成已命名类的编译字节码 ,并且可选地,为一个或多个协议和/或接口生成方法.它们适用于动态和交互式开发,无需进行AOT编译,并且可以在单个会话过程中重新评估.它们类似于使用命名字段生成数据结构时的defstruct,但与defstruct的不同之处在于:[...]

所以是的,如果可以从Java获得.注意命名.

作为旁注,您可能希望看一下从Java调用Clojure.