tags:

views:

52

answers:

2

How can I implement the ContactService interface without getting warning about unchecked conversions from the compiler:

interface ContactsService
{
    <T extends Response> T execute(Action<T> action);
}

interface Action<T extends Response> { }

interface Response{ }

class GetDetailsResponse implements Response {}

If I return an instance of GetDetailsResponse then I get the warning: Unchecked overriding: return type requires unchecked conversion

This is an example from the gwt best practices presentation at google io.

+2  A: 

I'm guessing you tried something like:

class MyService implements ContactsService {
    @Override
    public <T extends Response> T execute(Action<T> action) {
        return (T)new GetDetailsResponse();
    }
}

The problem with this is that I might have another class MyResponse that implements Response. Then I can call:

Action<MyResponse> action = new Action<MyResponse>();
// you can't actually instantiate an interface, just an example
// the action should be some instance of a class implementing Action<MyResponse>
MyReponse r = myService.execute(action);

But the execute method returns an instance of GetDetailsResponse, which is incompatible with MyReponse. You need to return the type T, which is given by the action you pass to execute.

As far as I can tell you can't instantiate a new variable of type T inside execute (not without some unchecked casts anyway). You probably need the action class to have a way to give you a Response instance that you can return from execute. Something like this:

interface Response {
    void setWhatever(String value);
}

interface Action<T extends Response> {
    T getResponse();
}

class MyAction implements Action<GetDetailsResponse> {
    @Override
    public GetDetailsResponse getResponse() {
        return new GetDetailsResponse();
    }
}

class MyService implements ContactsService {
    @Override
    public <T extends Response> T execute(Action<T> action) {
        T response = action.getResponse();
        // do something to Response here like
        response.setWhatever("some value");
        return response;
    }
}
Andrei Fierbinteanu
In absense of the asker, I'd have to upvote this and assume this is what's going on. In short, you can't have a generic return type and return something non-generically!
Mark Peters
A: 

To implement ContactsService, you must be capable of handling any kind of Response. The user might pass you an Action<FooResponse> and expect a FooResponse back, or might give an Action<BarResponse> and want a BarResponse. If you're not capable of doing that, then you don't satisfy the interface requirements.

If the interface wants to admit implementations that support only one kind of Response, then it would itself be generified on <T extends Response>, instead of only its method.

Kevin Bourrillion