如何使用Clojure的gen-class创建多个Java成员变量

Mar*_*ars 6 java clojure clojure-java-interop

这个答案约Clojure的Java的互操作一个非常古老的问题,介绍了如何使用gen-class:state:init关键字来创建一个单一的公共实例变量从Java访问.如果您只需要一个可用于Java类的数据,或者您可以要求Java类使用读取函数(例如,存储在状态变量中的映射),这就足够了.该方法还允许数据改变,例如通过将atoms 存储在状态变量中.

如果我想创建多个可直接在Java类中读取的实例变量,该怎么办?这可能吗?例如,我可以编译以下文件并执行Bar该类,并查看foo.bar打印出来的值42 .

Foo.clj:

(ns students.Foo
  (:gen-class
    :name students.Foo
    :state bar
    ; :state baz
    :init init))

(defn -init
  []
  [[] 42])
Run Code Online (Sandbox Code Playgroud)

Bar.java:

package students;

public class Bar {

    public static void main(String[] args) {
        Foo foo = new Foo();
        System.out.println(foo.bar);
        // System.out.println(foo.baz);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我取消注释baz行,Bar.java将无法编译 - 编译器似乎随机创建barbaz作为状态变量Foo,因此只有其中一个可用Bar.无论如何,我没有看到如何初始化barbaz使用init函数.

tno*_*oda 3

gen-class宏不支持定义多个公共字段。你必须使用defrecord宏或deftype宏来代替。

(defrecord Foo [bar baz])
Run Code Online (Sandbox Code Playgroud)

不幸的是,defrecord宏和deftype宏都没有准备一种方法来定义它们的构造函数。因此,在必须初始化多个实例变量的情况下,用 Java 编写 Java 类并没有什么可耻的。