【问题标题】:No matching method with Clojure Java interop using reify没有使用 reify 的 Clojure Java 互操作的匹配方法
【发布时间】:2023-03-21 14:06:01
【问题描述】:

我对某个 Clojure/Java 互操作存在误解。

我正在使用 Pi4J 库,我想在 GPIO 引脚上获得一个侦听器。

使用文档:https://pi4j.com/1.2/usage.html(在“Listen for Pin Changes”下)给出了以下示例:

public static class GpioUsageExampleListener implements GpioPinListenerDigital {
    @Override
    public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) {
        // display pin state on console
        System.out.println(" --> GPIO PIN STATE CHANGE: " + event.getPin() + " = "
                + event.getState());
    }
}

// create and register gpio pin listener
myButton.addListener(new GpioUsageExampleListener());

还有一个示例应用程序:https://pi4j.com/1.2/example/listener.html

其中有:

myButton.addListener(new GpioPinListenerDigital() {
    @Override
    public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) {
        // display pin state on console
        System.out.println(" --> GPIO PIN STATE CHANGE: " + event.getPin() + " = " + event.getState());
    }
});

所以,我正在尝试以下 Clojure 代码:

(import [com.pi4j.io.gpio GpioFactory GpioPinDigitalInput PinPullResistance RaspiPin]
        [com.pi4j.io.gpio.event GpioPinListenerDigital])

(def gpio (GpioFactory/getInstance))
(def mybutton (.provisionDigitalInputPin gpio RaspiPin/GPIO_02 PinPullResistance/PULL_DOWN))

(def gpio-listener (reify GpioPinListenerDigital
                    (handleGpioPinDigitalStateChangeEvent [this event]
                      (println "GPIO Event Occured"))))

(.addListener mybutton gpio-listener)

但我明白了:

No matching method addListener found taking 1 args for class com.pi4j.io.gpio.impl.GpioPinImpl

使用反射,我查看了可用于 mybutton 实例的方法,我可以看到该方法存在:

(clojure.reflect/reflect mybutton)

 :members
 #{{ 
    ;;; Stuff trimmed
   {:name addListener,
    :return-type void,
    :declaring-class com.pi4j.io.gpio.impl.GpioPinImpl,
    :parameter-types [java.util.List],
    :exception-types [],
    :flags #{:public :synchronized}}
   {:name addListener,
    :return-type void,
    :declaring-class com.pi4j.io.gpio.impl.GpioPinImpl,
    :parameter-types [com.pi4j.io.gpio.event.GpioPinListener<>],
    :exception-types [],
    :flags #{:varargs :public :synchronized}}}}

我已经成功地对照 GpioPinListener 检查了 gpio-listener 的类型。

(cast com.pi4j.io.gpio.event.GpioPinListener gpio-listener)
#object[user$reify__7404 0x11251bd "user$reify__7404@11251bd"]

我尝试将参数类型提示给 GpioPinListener,但我得到了相同的结果。

我缺乏 Clojure 和 Java 知识,这让我很失望,所以我有点不知道下一步该往哪里看,但我确信这是非常基础的东西。

【问题讨论】:

    标签: clojure clojure-java-interop


    【解决方案1】:

    我无法对此进行测试,但如果您注意到 the docs,您会发现 addListener 实际上是 var-arg,处理 var-arg 方法可能会令人困惑 due to misunderstandings of how var-arg methods in Java work

    addListener 期待一个 array 的侦听器(它被 Java var-arg 语法糖化了)。试试

    (.addListener mybutton
                  (into-array [gpio-listener])) 
    

    或者,由于addListener 实际上有一个List 重载,这也可能有效

    (.addListener myButton [gpio-listener])
    

    【讨论】:

    • 两者都有效。 :) 我根本没有注意到 var-args。我以后一定要记住它。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2019-07-18
    • 2015-06-12
    • 1970-01-01
    • 1970-01-01
    • 2014-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多