Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Groovy: Ambiguous method overloading for method

I'm struggling with groovy.lang.GroovyRuntimeException: Ambiguous method overloading for method exception in groovy-2.4.7.

I have 3 functional interfaces:

interface NoArg {
   Object handle();
}
interface OneArg {
   Object handle(Request req);
}
interface TwoArg {
   Object handle(Request req, Response rsp);
}

There is an App.java which provides some overloaded methods like:

public class App {
  void get(String pattern, NoArg handler) {
    ...
  }
  void get(String pattern, OneArg handler) {
    ...
  }
  void get(String pattern, TwoArg handler) {
    ...
  }
}

From Java I can make calls like:

{
  get("/", () -> "OK");
  get("/", req -> "OK");
  get("/", (req, rsp) -> rsp.send("OK"));
}

It works perfectly in Java, but I got an Ambiguous method overloading for method in Groovy when I just try:

{
   get("/", {-> "OK"})
}

Here is the full stacktrace:

21:34:13.502 [ERROR] [system.err] groovy.lang.GroovyRuntimeException: Ambiguous method overloading for method app.App#get. 21:34:13.502 [ERROR] [system.err] Cannot resolve which method to invoke for [class java.lang.String, class app.App$_closure1] due to overlapping prototypes between: 21:34:13.502 [ERROR] [system.err] [class java.lang.String, interface app.NoArg] 21:34:13.502 [ERROR] [system.err] [class java.lang.String, interface app.OneArg] 21:34:13.502 [ERROR] [system.err] [class java.lang.String, interface app.TwoArg]

Am I missing something? Or this isn't supported in Groovy?

Thanks.

like image 846
Edgar Espina Avatar asked Oct 25 '16 00:10

Edgar Espina


1 Answers

You will need to cast it to NoArg there is no implicit conversion to interface (like with the Java lambdas)

Example:

class Request{}

class Response{}

interface NoArg {
   Object handle();
}
interface OneArg {
   Object handle(Request req);
}
interface TwoArg {
   Object handle(Request req, Response rsp);
}

public class App {
  void get(String pattern, NoArg handler) {
    println(handler.handle())
  }
  void get(String pattern, OneArg handler) {
    println(handler.handle(new Request()))
  }
  void get(String pattern, TwoArg handler) {
    println(handler.handle(new Request(),new Response()))
  }
}

def app = new App()
app.get('/', {'NoArg'} as NoArg)
app.get('/', {req->'OneArg'} as OneArg)
app.get('/', {req,res -> 'TwoArg'} as TwoArg) 

Will print

NoArg
OneArg
TwoArg

Check it out: https://groovyconsole.appspot.com/edit/6196672648445952

like image 91
Strelok Avatar answered Sep 22 '22 08:09

Strelok