Clojure - 从另一个命名空间访问gen-class的语法问题

时间:2014-01-27 18:42:14

标签: clojure clojure-java-interop

似乎lein在重新编译代码方面无法预测。我在一个目录中有一个gen-class文件,试图在另一个目录中访问它。例如,给定这个gen-class:

(ns a.Target
    (:gen-class
     :state state
     :init  init
     :constructors {[String String] []}))

(defn -init
  [m1  m2]
  [[]  (atom {"A" m1 "B" m2})])

(defn -deref
  [this]
  @(.state this))

尝试从另一个名称空间访问它,减少到尝试随机变化1,2,3:

(ns b.runner
    (:require [a.Target  ] :as Target) ;1
    (:import '(a Target))              ;2
)

(compile 'a.Target) ;3

似乎没有语法会识别" Target"而不是" a.Target",所以在我如何处理gen-class方面显然有些不正确。这是一个问题,因为我试图使用带注释的提供程序方法访问我们的guice-injectors,并且注释语法似乎不接受完整或简单的类规范:

(definterface TargetProvider (^a.Target getTarget [this] ))
=> Exception in thread "main" java.lang.UnsupportedOperationException: nth not supported on this type:

或简化的:

(definterface TargetProvider (^Target getTarget [this] ))
=> Can't find class java.lang.Target

1 个答案:

答案 0 :(得分:3)

ns表达式应为(ns b (:import a.Target)),不需要使用:require来导入类。由于ns是宏,因此不会评估:require:use和其他选项中的所有符号,因此无需引用它们。使用以下ns声明,您的definterface表达式应该有效。

(ns b
  (:import a.Target))

(definterface TargetProvider [^a.Target getTarget []])

(->> b.TargetProvider .getMethods seq)
;= (#<Method public abstract a.Target b.TargetProvider.getTarget()>)

修改

这是使用上面定义的TargetProvider接口的代理代码,我认为这是您在评论中要求的内容。

请注意,我还修改了接口的getTarget方法的声明,删除了this参数,因为它实际上没有接收当前实例的引用。使用proxy时,会隐式绑定this本地(有关详细信息,请参阅here)。

(let [x (proxy [TargetProvider] []
          (getTarget [] (Target. "x" "y")))]
  (.getTarget x))