Нет метода сопоставления с Clojure Java-взаимодействием с использованием reify - PullRequest
1 голос
/ 10 мая 2019

У меня неправильное представление об определенном взаимодействии Clojure / Java.

Я использую библиотеку Pi4J и хочу получить прослушиватель на выводе GPIO.

Документация по использованию:https://pi4j.com/1.2/usage.html (в разделе «Прослушивание изменений выводов») приводит следующий пример:

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}}}}

Я успешно проверил тип gpio-listener для GpioPinListener.

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

Я попытался напечатать подсказку параметра для GpioPinListener, но я получил тот же результат.

Мне не хватает знаний о Clojure и Java, поэтому я немного растерялся, где искать дальше, но яконечно, это что-то действительно простое.

1 Ответ

3 голосов
/ 10 мая 2019

Я не могу это проверить, но если вы заметите документы , вы увидите, что addListener на самом деле является var-arg, а работа с методами var-arg может сбить с толку из-за недопонимания того, как методы var-arg в Java работают .

addListener ожидает массив слушателей (который отключен синтаксисом Java var-arg).Попробуйте

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

Или, поскольку addListener на самом деле имеет перегрузку List, это тоже может работать

(.addListener myButton [gpio-listener])
...