Groovy:方法的二义性方法重载

Edg*_*ina 5 groovy lambda closures

groovy.lang.GroovyRuntimeException: Ambiguous method overloading for method在 groovy-2.4.7 中遇到异常。

我有 3 个功能接口:

interface NoArg {
   Object handle();
}
interface OneArg {
   Object handle(Request req);
}
interface TwoArg {
   Object handle(Request req, Response rsp);
}
Run Code Online (Sandbox Code Playgroud)

有一个 App.java 提供了一些overloaded方法,如:

public class App {
  void get(String pattern, NoArg handler) {
    ...
  }
  void get(String pattern, OneArg handler) {
    ...
  }
  void get(String pattern, TwoArg handler) {
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)

从 Java 我可以拨打如下电话:

{
  get("/", () -> "OK");
  get("/", req -> "OK");
  get("/", (req, rsp) -> rsp.send("OK"));
}
Run Code Online (Sandbox Code Playgroud)

它在 Java 中运行良好,但是Ambiguous method overloading for method当我尝试时,我在 Groovy 中得到了一个:

{
   get("/", {-> "OK"})
}
Run Code Online (Sandbox Code Playgroud)

这是完整的堆栈跟踪:

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]

我错过了什么吗?或者这在 Groovy 中不受支持?

谢谢。

Str*_*lok 5

您需要将其NoArg强制转换为没有隐式转换到接口(如 Java lambdas)

例子:

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) 
Run Code Online (Sandbox Code Playgroud)

会打印

NoArg
OneArg
TwoArg
Run Code Online (Sandbox Code Playgroud)

看看:https : //groovyconsole.appspot.com/edit/6196672648445952


Edg*_*ina 1

我最终编写了一个扩展模块

/**
 * Example on how to hack Groovy so we can use groovy closure on script routes.
 */
class AppExtension {

  private static Object toHandler(Closure closure) {
    if (closure.maximumNumberOfParameters == 0) {
      NoArg handler = { closure() }
      return handler
    } else if (closure.maximumNumberOfParameters == 1) {
      OneArg handler = { req -> closure(req) }
      return handler
    }
    TwoArg handler = { req, rsp -> closure(req, rsp) }
    return handler
  }

  static void get(App self, String pattern, Closure closure) {
    self.get(pattern, toHandler(closure));
  }

  static void post(App self, String pattern, Closure closure) {
    self.get(pattern, toHandler(closure));
  }
}
Run Code Online (Sandbox Code Playgroud)

我创建了get一个接受Closure. 然后我检查闭包参数并将闭包转换为所需的接口。