【问题标题】:Groovy and Java Callbacks / Lambdas (Closures with a type)Groovy 和 Java 回调/Lambdas(带有类型的闭包)
【发布时间】:2014-08-09 05:41:55
【问题描述】:

这是我在 Java 中的回调(future 是 Mongo 的 SingleFutureResult):

future.register(new SingleResultCallback<ArrayList<Document>>() {
    @Override
    void onResult(ArrayList<Document> documents, MongoException e) {
        //do something
    }
 })

在 Java 8 中,我可以使用 Lambda 使其看起来像这样:

future.register((documents, e) -> {
    //do something
});

整洁。但是,我想在 Groovy 类中调用该 Java 方法。我知道 Groovy 目前不支持 jdk8 lambda 的语法,但文档总是强调它们有闭包。如果我尝试在这种情况下使用闭包,它会失败,因为闭包是Closure 类型,而不是SingleResultCallback 类型。有没有办法拥有不同类型的闭包之类的东西?有没有其他方法可以很好地完成这项工作?我知道我可以使用第一个解决方案,但在 groovy 类中这看起来很奇怪。

【问题讨论】:

    标签: groovy lambda closures


    【解决方案1】:

    使用 Groovy 的闭包语法:

    future.register( { documents, e -> 
        //do something
    });
    

    如果register 方法重载有歧义,则在闭包声明后可能需要as SingleResultCallback:

    future.register { documents, e -> } as SingleResultCallback
    

    这是一个模棱两可的场景:

    interface SingleResultCallback<T> {
        def onResult(T result)
    }
    
    interface Callback { def onResult(obj) }
    
    class Future {
        void register(SingleResultCallback s) {
            println "registered: ${s.onResult(10)}"
        }
    
        void register (Callback r) {
            println "runnable=${r.onResult()}"
        }
    }
    
    new Future().register { it ** 2 }
    

    失败的原因是:

    Caught: groovy.lang.GroovyRuntimeException: 
        Ambiguous method overloading for method Future#register.
    Cannot resolve which method to invoke for [class Sam$_run_closure1] due 
        to overlapping prototypes between:
      [interface Callback]
      [interface SingleResultCallback]
    

    如果SingleResultCallback 有多个方法,则映射强制是处理它的好方法:

    interface SingleResultCallback<T> {
        def onResult(T result)
        def onError
    }
    
    class Future {
        def register(SingleResultCallback s) {
            "registered: ${s.onResult(10)}"
        }
    
    }
    
    assert new Future().register( 
        [onResult: { it ** 2 } ] as SingleResultCallback ) == "registered: 100"
    

    【讨论】:

    • 通过“歧义”,我认为他的意思是“如果注册方法被重载”
    • 方法寄存器没有重载,不应该有歧义。这是来源:github.com/mongodb/mongo-java-driver/blob/3.0.x/driver/src/main/…。由于冲突类型No signature of method: org.mongodb.operation.SingleResultFuture.register() is applicable for argument types: (com.mycompany.myproject.MyService$_handle_closure1),第一个代码 sn-p 失败。第二个片段是我一直在寻找的,但到目前为止找不到...您能否指出有关歧义的更多细节?
    • 你使用的是什么版本的 groovy? Sam 类型强制需要 2.3+
    • Groovy 版本是 2.3.3
    • @Dónal,确实,已修复。
    【解决方案2】:

    我知道问题提出已经有一段时间了,而且它已经得到答复,但我也想使用 Groovy Closure 作为回调添加这个示例(更多信息请访问https://groovy-lang.org/closures.html)。

    Groovy 也支持作为对象的闭包,例如:

    Closure callback = { println 'Done!' } 
    callback()
    

    输出将是:

    Done!
    

    以上只是另一个例子:

    def callbackList(){
          def list = ["RICE", "BEANS", "EGGS"]
          iterableList(list, { elem ->
            println elem
        })
    }
    
    def iterableList(list, callback){
       list.each {
         callback(it)
       }
    }
    

    输出将是:

    RICE 
    BEANS
    EGGS
    

    【讨论】:

      猜你喜欢
      • 2011-08-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-26
      • 2019-06-23
      • 1970-01-01
      • 2018-10-29
      相关资源
      最近更新 更多