5

I am trying to 'implement' the following Java interface from JGroups with reify.

public interface MessageListener extends StateListener {
   /**
    * Called when a message is received.
    * @param msg
    */
    void receive(Message msg);

    /** Called when a batch of messages is received */
    default void receive(MessageBatch batch) {
        for(Message msg: batch) {
            try {receive(msg);}
            catch(Throwable t) {}
        }
    }
}

In this case the receive method is present twice, with one parameter each (and different types, of course). When I try to reify with the following code in CIDER:

(reify org.jgroups.MessageListener (receive[#^org.jgroups.Message msg] 
                                     (println msg)))

I get an error message:

CompilerException java.lang.IllegalArgumentException: Can't define method not in interfaces: receive, compiling:(*cider-repl clj-groups*:49:21)

As receive is definitely available in the interface, I assume that this issue is related to the overloaded method and my typ hint is not working. What am I doing wrong?

Edit: After changing the code according to Lees comment:

(reify org.jgroups.MessageListener (receive[this #^org.jgroups.Message msg]                                     
                                     (println msg)))

the error message changed:

CompilerException java.lang.IllegalArgumentException: Mismatched return type: receive, expected: void, had: java.lang.Object, compiling:(*cider-repl clj-groups*:80:21)
javahippie
  • 806
  • 10
  • 25
  • 2
    You at least need to add a `this` parameter: `(receive [this msg] ...)`. – Lee Feb 26 '17 at 20:20
  • http://stackoverflow.com/questions/21000267/clojure-reify-a-java-interface-with-overloaded-methods – mishadoff Feb 26 '17 at 20:35
  • Possible duplicate of [Clojure reify a Java interface with overloaded methods](http://stackoverflow.com/questions/21000267/clojure-reify-a-java-interface-with-overloaded-methods) – mishadoff Feb 26 '17 at 20:36
  • Difference between the possible duplicate and me is that the methods have the same parameter count and type hinting is needed. – javahippie Feb 26 '17 at 20:37
  • Thank you for your comment, @Lee. I updated the question – javahippie Feb 26 '17 at 20:42
  • Try adding `^void` between `receive` and `[` to type hint the return value. l don't know whether that will work. – Mars Feb 27 '17 at 06:40
  • Mars, Unfortunately, not. The error message does not change – javahippie Feb 27 '17 at 06:45

1 Answers1

8

The following works when you add missing this argument and hint the return and argument types:

$ boot -d org.jgroups/jgroups:4.0.0.Final repl

(import '(org.jgroups MessageListener Message) '(org.jgroups.util MessageBatch))
;;=> org.jgroups.util.MessageBatch

(def listener
  (reify MessageListener
    (^void receive [this ^Message msg] (println "Message"))
    (^void receive [this ^MessageBatch batch] (println "MessageBatch"))))
;;=> #'boot.user/listener

(.receive listener (Message.))
;; Message
;;=> nil

(.receive listener (MessageBatch. 0))
;; MessageBatch
;;=> nil
Piotrek Bzdyl
  • 12,965
  • 1
  • 31
  • 49
  • 3
    From the doc on reify: "If you supply any hints at all, no inference is done, so all hints (or default of Object) must be correct, for both arguments and return type." – Travis Rodman Nov 18 '18 at 07:05