在 Clojure 中扩展 Java 接口时出错

Posted

技术标签:

【中文标题】在 Clojure 中扩展 Java 接口时出错【英文标题】:Errors extending a Java Interface in Clojure 【发布时间】:2016-04-26 10:40:50 【问题描述】:

我有一个基本的 Java 接口定义如下:

public interface Action 
    void execute(Metadata var1, Parameter var2);

我正在尝试在 Clojure 中扩展它,但不断出错。将类导入我的命名空间后,我尝试使用reify,如下所示:

(defn action [action-fn]
  (reify Action
    (execute [metadata parameter] (action-fn metadata parameter))))

但这会引发编译器非法参数异常:

CompilerException java.lang.IllegalArgumentException: Can't define method not in interfaces: execute

接下来我尝试使用proxy

(defn action [action-fn]
  (proxy [Action] []
    (execute [metadata parameter] (action-fn metadata parameter))))

编译成功,我的编辑器(IntelliJ + Cursive)通过边框装饰导航到接口定义,但尝试在生成代理上调用执行失败:

(.execute (action (fn [_ _] "Test action")))

抛出以下内容:

IllegalArgumentException No matching field found: execute for class

最后我尝试使用 deftype 如下:

(deftype cljAction [action-fn]
  Action
  (execute [metadata parameter] (action-fn metadata parameter)))

引发与reify 相同的编译器错误,例如:

CompilerException java.lang.IllegalArgumentException: Can't define method not in interfaces: execute

浏览各种博客文章和 SO 答案似乎表明这是论点数量的问题,但我不知道如何解决它。我做错了什么??

【问题讨论】:

【参考方案1】:

您缺少函数中的 this 引用。所以你想要的是这样的:

(defn action [action-fn]
  (reify Action
    (execute [this metadata parameter] (action-fn metadata parameter))))

显然,因为您没有使用它,您可以将其称为 _ 或您认为最有意义的任何名称。当你调用你想要的函数时:

(.execute (action action-fn) metadata parameter)

这与您实现协议时略有不同。请参阅https://clojuredocs.org/clojure.core/definterface 了解更多信息。

【讨论】:

啊,成功了,谢谢!包括this 引用消除了编译器错误,REPL 中的以下代码按预期工作:(.execute (action (fn [metadata parameter] (println "Test action"))) nil nil) @OliverMooney,很高兴为您提供帮助!【参考方案2】:

ponzao 的回答是正确的。但请注意,Cursive 实际上可以为您填写存根:您可以编写 (reify Action) 然后(在该表单中的某处使用光标)选择 Code->Generate... 并选择实现方法.然后草书将用正确的形式填写存根。这目前仅在实现接口而非协议时有效。

【讨论】:

我没有意识到,谢谢!我主要使用 IntelliJ 作为 Cursive 的主机,到目前为止,大多数面向 Java 的菜单选项都是未知数...

以上是关于在 Clojure 中扩展 Java 接口时出错的主要内容,如果未能解决你的问题,请参考以下文章

Clojure:实现有状态的 Java 接口

Java扩展Nginx之二:编译nginx-clojure源码

clojure 中交错的扩展

精选版:用Java扩展Nginx(nginx-clojure 入门)

精选版:用Java扩展Nginx(nginx-clojure 入门)

精选版:用Java扩展Nginx(nginx-clojure 入门)