首页 文章

Groovy和Java Callbacks / Lambdas(带有类型的闭包)

提问于
浏览
0

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

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

使用Java 8,我可以使用Lambdas使它看起来像这样:

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

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

1 回答

  • 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 有多个方法,那么 Map 强制是处理它的好方法:

    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"
    

相关问题