Reputation: 2553
This is a callback I have in Java (future
is a Mongo's SingleFutureResult
):
future.register(new SingleResultCallback<ArrayList<Document>>() {
@Override
void onResult(ArrayList<Document> documents, MongoException e) {
//do something
}
})
With Java 8 I can use Lambdas to make it look like this:
future.register((documents, e) -> {
//do something
});
Neat. However, I would like to call that Java method within a Groovy class. I know Groovy does currently not support jdk8 lambda's syntax, but the docs always stress that they have closures instead. If I try to use a closure in such a case it fails, as the closure is of type Closure
, and not of type SingleResultCallback
. Is there a way to have something like a closure with a different type? Is there any other way to make this work in a nice way? I know I can use the first solution, but that looks pretty weird within a groovy class.
Upvotes: 1
Views: 4881
Reputation: 531
I know it has been a while since the question was made, and it's already replied, but i would also to add this example using Groovy Closure as callback (to see more go at https://groovy-lang.org/closures.html).
Groovy also support Closure as an Object, for instance:
Closure callback = { println 'Done!' }
callback()
The output would be:
Done!
Above it's just another example:
def callbackList(){
def list = ["RICE", "BEANS", "EGGS"]
iterableList(list, { elem ->
println elem
})
}
def iterableList(list, callback){
list.each {
callback(it)
}
}
The output would be:
RICE
BEANS
EGGS
Upvotes: 1
Reputation: 14519
Use Groovy's closure syntax:
future.register( { documents, e ->
//do something
});
If there is ambiguity in a register
method overload, it might need as SingleResultCallback
after the closure declaration:
future.register { documents, e -> } as SingleResultCallback
This is an ambiguity scenario:
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 }
Which fails with:
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]
And if SingleResultCallback
had more than one method, a map coercion is a nice way to deal with it:
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"
Upvotes: 2