【问题标题】:How to create multiple Java member variables with Clojure's gen-class如何使用 Clojure 的 gen-class 创建多个 Java 成员变量
【发布时间】:2015-07-11 13:02:37
【问题描述】:

This answer 对关于 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])

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);
    }
}

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

【问题讨论】:

    标签: java clojure clojure-java-interop


    【解决方案1】:

    gen-class 宏不支持定义多个公共字段。您必须改用defrecord 宏或deftype 宏。

    (defrecord Foo [bar baz])
    

    不幸的是,defrecord 宏和deftype 宏都没有准备好方法来定义它们的构造函数。因此,在强制初始化多个实例变量的情况下,用 Java 编写 Java 类并不丢人。

    【讨论】:

    • 谢谢。没有羞耻,但没有乐趣;我更喜欢写 Clojure。令人失望。鉴于 Clojure 为与 Java 交互提供的所有工具,这似乎是一个任意限制。幸运的是,多个实例变量对我来说可能不是强制性的,但我想知道。
    • 基于Chas Emerick's Flowchart for choosing the right Clojure type definition formgen-class 可能是我当前项目的最佳选择。
    猜你喜欢
    • 2010-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-12
    • 2013-02-10
    • 2012-02-15
    • 1970-01-01
    相关资源
    最近更新 更多