我有一个基本的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失败:
(.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答案进行搜索似乎表明它存在争议的问题,但我不确定如何解决它。我做错了什么?
答案 0 :(得分:5)
您缺少该函数的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。
答案 1 :(得分:2)
(reify Action)
然后(用光标在某处),选择 Code-> Generate ... 并选择实施方法。然后草书将以正确的形式填充存根。这当前仅适用于实现接口而非协议。