【问题标题】:Generate class with static method from Clojure使用 Clojure 的静态方法生成类
【发布时间】:2014-04-08 16:12:56
【问题描述】:

我有一个想在 Java 中使用的 Clojure 库,但我无法生成正确的类。我想生成一个有效的类:

public class TokenStore {
    public static TokenStore Sns(Map<String, String> services) { /* ... */ }

    public String addToken(String token, String username, String service) { /* ... */ }
    public String findToken(String username, String service) { /* ... */ }
    public String sendNotification(String username, String service, String message) { /* ... */ }
}

这是我在 Clojure 中尝试做的事情:

(ns my.lib.token-java
  (:require [my.lib.token :refer :all])
  (:gen-class
   :name my.lib.TokenStore
   :methods [#^{:static true} [Sns [java.util.Map] TokenStore]]))

(defprotocol TokenStore
  (addToken [this token username service])
  (findToken [this username service])
  (sendNotification [this username service message]))

(defn -Sns [services]
  (let [ts (token-store (apply concat (for [[k v] (into {} coll)] [(keyword k) v]))]
    (reify TokenStore
      (addToken [this token username service]
        (add-token this token username service))
      (findToken [this username service]
        (find-token this username service))
      (sendNotification [this username service message]
        (send-notification this username service message)))))

但是当我尝试编译它时,我得到:

: jmglov@alhana; lein jar
Compiling orron-iii.push-java
Exception in thread "main" java.lang.ClassNotFoundException: java.lang.TokenStore, compiling:(orron_iii/push_java.clj:1:1)

谁能给我一个简单的例子来说明如何做到这一点?

【问题讨论】:

  • 尝试将 :methods 部分中的 TokenStore 更改为 my.lib.TokenStore。
  • 不,这没有帮助。
  • 是的,您的协议和类具有相同名称这一事实可能会导致冲突,因为协议会导致生成自己的接口。我的建议是使用您想要的方法签名在 Java 中定义 TokenStore 接口,然后在 Clojure 中创建一个工厂类来生成该接口的实现。但你的方式也行得通。

标签: java clojure interop


【解决方案1】:

这不是我问题的直接答案,但它可能是实现我想要的更好的方法。这有点像“医生,我这样做的时候很痛。” “那就别这样了!”那类的东西。 :)

我使用标准 gen-class foo 创建了一个扩展 java.lang.Object 的类,并巧妙地包装了我的 Clojure 令牌存储内容(在纯 Clojure my.lib.token 文件中定义)。

(ns my.lib.token-java
  (:require [my.lib.token :as t])
  (:gen-class
   :name my.lib.TokenStore
   :constructors {[java.util.List] []}
   :init initialise
   :state localstate
   :methods [[addToken [String String String] String]
             [findToken [String String] String]
             [sendNotification [String String String] String]]))

(defn- keywordise [coll]
  (flatten (map (fn [[k v]] [(keyword k) v]) (partition 2 coll))))

(defn -initialise [services]
  (let [token-store (apply t/sns-token-store (keywordise services))]
    [[] (ref token-store)]))

(defn -addToken [this service username token]
  (t/add-token @(.localstate this) (keyword service) username token))

(defn -findToken [this service username]
  (t/find-token @(.localstate this) (keyword service) username))

(defn -sendNotification [this service username message]
  (p/send-notification @(.localstate this) (keyword service) username message))

我现在可以像这样在 Java 中使用它:

import my.lib.TokenStore;
import java.util.Arrays;

public class TokenTool {
    public static void main(String[] args) {
        TokenStore tokenStore = new TokenStore(Arrays.asList("APNS", "arn:aws:sns:..."));

        String deviceId = tokenStore.findDevice("APNS", "foo");
        System.out.println("Device is: " + deviceId);

        tokenStore.sendNotification("APNS", "foo", "Test for echo");
    }
}

这似乎工作得很好。

【讨论】:

    猜你喜欢
    • 2014-12-13
    • 1970-01-01
    • 1970-01-01
    • 2012-05-24
    • 2015-02-28
    • 2010-10-10
    • 2012-06-25
    • 2015-04-08
    • 2011-01-17
    相关资源
    最近更新 更多