目前,我有一个功能齐全的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协议和记录可用?
答案 0 :(得分:6)
每个Clojure协议也是具有相同名称和方法的Java接口。如果我从ibm developerworks中提取示例,我们会看到:
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton.buttonWithType(UIButtonType.System) as UIButton
button.frame = CGRectMake(100, 100, 100, 50)
button.backgroundColor = UIColor.greenColor()
button.setTitle("Test Button", forState: UIControlState.Normal)
button.addTarget(self, action: "buttonAction:", forControlEvents:UIControlEvents.TouchUpInside)
self.view.addSubview(button)
}
func buttonAction(sender:UIButton!) {
println("Button tapped") {
}
相当于:
(ns com.amalgamated)
(defprotocol Fulfillment
(invoice [this] "Returns an invoice")
(manifest [this] "Returns a shipping manifest"))
Clojure.org也有一些(相当简洁的)信息。
希望参与协议的Java客户端最多可以这样做 通过实现协议生成的接口有效地实现。外部 协议的实现(当你想要一个时需要它 类或类型不在您的控制中参与协议)可以 使用extend构造提供:
package com.amalgamated; public interface Fulfillment { public Object invoice(); public Object manifest(); }
如果您的目标是性能,可以考虑使用(extend AType AProtocol
{:foo an-existing-fn
:bar (fn [a b] ...)
:baz (fn ([a]...) ([a b] ...)...)} BProtocol
{...} ...)
,其使用类似于协议。此SO post还包含有关如何使用它的详细信息:
definterface
(definterface Foo
[^int foo [x ^String y]]
[^void bar [^ints is]])
似乎比协议faster。
同样,definterface
(以及record
和deftype
)将生成Java类。
同样,Clojure.org/datatypes提供了有用的信息(强调我的):
deftype和 defrecord 动态生成a的编译字节码 带有一组给定字段的命名类,以及可选的方法 一个或多个协议和/或接口。它们适合动态 和交互式开发,无需进行AOT编译,并且可以 在单个会话过程中重新评估。它们类似于 defstruct生成具有命名字段的数据结构,但不同 来自defstruct:[...]
所以是的,如果可以从Java获得。 注意命名。
作为旁注,您可能需要查看calling Clojure from Java。