How to reify Java Interfaces with overloaded method?
Asked Answered
F

1

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)
Fraud answered 26/2, 2017 at 20:9 Comment(7)
You at least need to add a this parameter: (receive [this msg] ...).Roofing
#21000767Marlin
Possible duplicate of Clojure reify a Java interface with overloaded methodsMarlin
Difference between the possible duplicate and me is that the methods have the same parameter count and type hinting is needed.Fraud
Thank you for your comment, @Lee. I updated the questionFraud
Try adding ^void between receive and [ to type hint the return value. l don't know whether that will work.Spermary
Mars, Unfortunately, not. The error message does not changeFraud
V
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
Vibrissa answered 27/2, 2017 at 10:45 Comment(1)
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."Piazza

© 2022 - 2024 — McMap. All rights reserved.