Tom
Tom

Reputation: 114

Overloading a method in Groovy using Closure arguments with different return types

I'm reasonably proficient with Groovy insofar as my job requires, but not having a background in OOP means that some things still elude me, so apologies if some of the wording is a little off here (feel free to edit if you can make the question clearer).

I'm trying to create an overloaded method where the signature (ideally) differs only in the return type of the single Closure parameter. The Closure contains a method call that returns either an ItemResponse or ListResponse object, both of which could contain an object/objects of any type (which is the type I would like to infer).

The following code is a simplified version of what I'm trying to implement - an error handling method which takes a reference to a service call, safely attempts to resolve it, and returns the item/items from the response as appropriate:

public <T> T testMethod(Closure<ItemResponse<T>> testCall) {
    testCall.call().item as T
}

public <T> List<T> testMethod(Closure<ListResponse<T>> testCall) {
    testCall.call().items as T
}

Obviously this doesn't work, but is there any alternate approach/workaround that would achieve the desired outcome?

Upvotes: 0

Views: 388

Answers (2)

defectus
defectus

Reputation: 1987

As mentioned by yourself and @jeffscottbrown, you can't have two methods with the same parameters but different return value. The workaround I can see here is to use a call-back closure. The return value of your testMethod would default to Object and you would provide an "unwrapper" that would the bit after the closure call (extract item or items). Try this out in your GroovyConsole:

class ValueHolder <T> {
    T value
}

Closure<List<Integer>> c = {
    [1]
}

Closure<ValueHolder<String>> d = {
    new ValueHolder(value:'hello world')
}

Closure liu = {List l ->
    l.first()
}

Closure vhsu = {ValueHolder vh ->
    vh.value
}

// this is the generic method
public <T> Object testMethod(Closure<T> testCall, Closure<T> unwrapper) {
    unwrapper(testCall.call()) as T
}

println testMethod(c, liu)
println testMethod(d, vhsu)

It works with both a list or a value holder.

Upvotes: 1

Jeff Scott Brown
Jeff Scott Brown

Reputation: 27210

I'm trying to create an overloaded method where the signature (ideally) differs only in the return type of the single Closure parameter.

You cannot do that because the return type is not part of the method signature. For example, the following is not valid:

class Demo {
    int doit() {}
    String doit() {}
}

Upvotes: 1

Related Questions