从Clojure生成包含静态方法的类

4

我有一个Clojure库,想在Java中使用,但是我遇到了生成正确类的问题。我希望生成一个有效的类:

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。 - Alex
1
不,那没帮助。 - Josh Glover
1
是的,你的协议和类名称相同很可能会导致冲突,因为该协议会生成自己的接口。我的建议是在Java中定义TokenStore接口并使用你想要的方法签名,然后在Clojure中创建一个工厂类来生成该接口的实现。但你的方式也可以。 - Alex
1个回答

3
这不是对我的问题的直接回答,但它可能是实现我想要的更好的方法。这有点像“医生,我做这个动作时很疼。”“那就别做那个动作!”的感觉。 :)
我使用了标准的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");
    }
}

这似乎非常有效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接