【问题标题】:Declare Member Variables with gen-class in Clojure在 Clojure 中使用 gen-class 声明成员变量
【发布时间】:2010-12-07 17:31:23
【问题描述】:

我正在学习如何在 Clojure 中扩展 Java 类,但我没有看到声明新成员变量的方法;我只看到方法的方法。

(ns test.aclass
  (:gen-class
    :methods [[foo [] String]]))

是否有:members 关键字或其他声明成员变量的方式?

【问题讨论】:

    标签: clojure


    【解决方案1】:

    :state name

    如果提供,将创建一个具有给定名称的公共最终实例字段。您必须提供 :init 函数才能为状态提供值。请注意,虽然是最终状态,但状态可以是 ref 或代理,支持创建具有事务或异步突变语义的 Java 对象。

    website 上有一个如何使用它的示例。

    【讨论】:

      【解决方案2】:

      我也遇到了一些麻烦。下面的例子并不优雅,但在 Clojure 而不是 Java 中编写愚蠢的小胶水类非常简单。请注意,我为线程安全所做的只是确保字段更新是原子的——我没有做任何其他并发性的事情,这可能会产生真正的影响。

      init 方法为对象创建实例变量。 setfieldgetfield 宏是原子更新记账的缩写。

      (ns  #^{:doc "A simple class with instance vars"
          :author "David G. Durand"}
         com.tizra.example )
      
      (gen-class
        :name com.tizra.example.Demo
        :state state
        :init init
        :prefix "-"
        :main false
        :methods [[setLocation [String] void]
                  [getLocation [] String]]
      )
      
      (defn -init []
        "store our fields as a hash"
        [[] (atom {:location "default"})])
      
      (defmacro setfield
        [this key value]
        `(swap! (.state ~this) into {~key ~value}))
      
      (defmacro getfield
        [this key]
        `(@(.state ~this) ~key))
      
      (defn -setLocation [this ^java.lang.String loc]
        (setfield this :location loc))
      
      (defn ^String -getLocation
        [this]
        (getfield this :location))
      

      您必须对其进行编译,并确保生成的存根类在您的类路径中,然后您可以像任何其他 java 类一样创建实例等。

      => (com.tizra.example.Demo.)
      #<Demo com.tizra.example.Demo@673a95af>
      
      => (def ex (com.tizra.example.Demo.))
      #'user/ex
      
      => (.getLocation ex)
      "default"
      
      => (.setLocation ex "time")
      nil
      
      => (.getLocation ex)
      "time"
      

      我发现此博客上的较长摘要很有帮助:http://kotka.de/blog/2010/02/gen-class_how_it_works_and_how_to_use_it.html

      【讨论】:

        【解决方案3】:

        proxy 的主体是一个词法闭包,因此您可以围绕您需要的任何变量进行闭包。如果,上帝保佑,你需要改变它们,然后关闭一个原子:

        (defn lying-list [init-size]
          (let [the-size (atom init-size)]
            (proxy [java.util.ArrayList] []
              (size [] @the-size)
              (remove [idx] (reset! the-size idx), true))))
        

        这里真的不需要实际的 Java 字段。

        【讨论】:

          猜你喜欢
          • 2015-07-11
          • 1970-01-01
          • 2019-01-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-04-04
          • 1970-01-01
          • 2012-02-15
          相关资源
          最近更新 更多