Java generics in an interface - java

I have run into a problem with generics in Java and I can't find a solution or example online of someone using generics in a similar fashion. I have a set of methods that are in the same request/response structure. For example, a user populates fields in the Request object, passes the object to a helper method, and they are returned a Response object. All of my request objects extend from a common Request super class (and similarly, Response objects from a Response super class). I would like my helper classes to also have a consistent structure so I have used an interface. Here is some code to illustrate...
Request super class:
public class SuperRequest {
// ...
}
Example Request subclass:
public class SubRequest extends SuperRequest {
// ...
}
Response super class:
public class SuperResponse {
// ...
}
Example response subclass:
public class SubResponse extends SuperResponse{
// ...
}
The interface:
public interface SomeInterface {
public <T extends SuperRequest, U extends SuperResponse> U someMethod(T request);
}
As you can see from the interface, I want to pass an object that is a child of SuperRequest and I want to return an object that is a child of SuperResponse. Here is my implementation:
public class SomeImplementation implements SomeInterface {
#Override
public SubResponse someMethod(SubRequest request) {
return null;
}
}
In Eclipse, I get compilation errors because the compiler tells me I have unimplemented methods and the #Override notation "does not override a supertype method".
Can anyone help me here? Is my syntax incorrect or is my understanding of generics a little off? Any help is greatly appreciated!

Try changing your interface and implementation to:
interface SomeInterface<T extends SuperRequest, U extends SuperResponse> {
public U someMethod(T request);
}
class SomeImplementation implements SomeInterface<SubRequest, SubResponse> {
#Override
public SubResponse someMethod(SubRequest request) {
return null;
}
}

As it stands, the implementation of SomeInterface must implement the parameterized method, i.e.:
public <T extends SuperRequest, U extends SuperResponse> U someMethod(T request);
It can't choose a particular Subclass to substitute for T and U.
The interface itself must be generic SomeInterface<T extends SuperRequest, U extends SuperResponse> and the subclass can then choose concrete implementations for T and U.

You have to declare the types as well when you implement the interface. Try this:
public class SomeImplementation implements SomeInterface<SubRequest,SubResponse> {
#Override
public SubResponse someMethod(SubRequest request) {
return null;
}
}

Related

Annotation Processor appears to break Java generics

Background
I was trying to use Annotation Processors, to generate implementations of specific Factory interfaces. Those interfaces look the following:
public interface ViewFactory<T extends View> {
<S extends Presenter<T>> T create(S presenter);
}
and
public interface PresenterFactory<T extends View> {
<S extends Presenter<T>> S create();
}
The Annotation Processor is doing the correct thing and generates a factory for each matching class, that is annotated with an corresponding annotation.
The Problem
The output of the Annotation Processor is the following:
public final class TestViewImplFactory implements ViewFactory {
public final TestView create(TestPresenter presenter) {
return new TestViewImpl(presenter);
}
}
and the corresponding other class:
public final class TestPresenterImplFactory implements PresenterFactory {
public final TestPresenter create() {
return new TestPresenterImpl();
}
}
The TestViewImplFactory however cannot be compiled. The error message is:
"Class 'TestViewImplFactory' must be declared abstract or implement
abstract method create(S) in 'ViewFactory'"
Java says, the following is correct:
#Override
public View create(Presenter presenter) {
return new TestViewImpl(presenter);
}
which would not work at all, considering that the user wants to know, which View will be returned and which Presenter is required. I would have expected that:
either both of the autogenerated files are wrong
or both are correct
because they both are really similar. I expected the first to be true.
What am I missing here?
If I add the Generic type to the TestViewImplFactory like this:
public final class TestViewImplFactory implements ViewFactory<TestView> {
#Override
public <S extends Presenter<TestView>> TestView create(S presenter) {
return new TestViewImpl(presenter);
}
}
The problem arises, that the constructor Parameter (which is of the Type TestPresenter) is incorrect. Changing the S to a concrete TestPresenter will, again, make the class not compilable for the same reason as above.
So, I stumbled across an "solution" that can be compiled.
What basically has to be done, is to change the ViewFactory interface to the following:
public interface ViewFactory<T extends View, S extends Presenter<T>> {
T create(S presenter);
}
So the class definition has the same Generic type, as the method in the Question above.
After compilation (this time with generic type specification), the output looks like this:
public final class TestViewImplFactory implements ViewFactory<TestView, TestPresenter> {
public TestViewImplFactory() {
}
public final TestView create(TestPresenter presenter) {
return new TestViewImpl(presenter);
}
}
This can be compiled and runs successfully.
This however does not answer the original question. Why is the generic explicitly stated in the type definition correct, but inherited and specified in the method declaration wrong and not compilable?
To be concrete: Why can Java inherit one Generic automatically (within the PresenterFactory) and the other ones not (within the ViewFactory, at the method and at the type declaration)?
Why it is not working:
public interface PresenterFactory<T extends View> {
<S extends Presenter<T>> S create();
}
This signature causes the compiler to infer S at the location where create() is called. S will be what ever you assign create() to as in:
FancyPresenter fp = presenterFactory.create();
SomeOtherPresenter sop = presenterFactory.create();
This implies that:
public TestPresenter create(){...}
is not an implementation of:
<S extends Presenter<T>> S create();
but a method override. There is no implementation of the interface' method. It's not even possible to provide any implementation with a concrete S. It's similar with:
public interface ViewFactory<T extends View> {
<S extends Presenter<T>> T create(S presenter);
}
Here the generic is again inferred on method invocation. So an implementation must accept every subtype of Presenter<T>. The only valid implementation for this is:
public interface ViewFactory<T extends View> {
T create(Presenter<T> presenter);
}
But the return type is dependent on the parameter presenter. This might work if presenter provides you with a method to create an instance of T only.
Why does the other solution work:
Binding the method's generic via the type means that an implementation of the interface provides the concrete type. So for one object you don't need to provide multiple different bindings. No matter where you call the create() method of PresenterFactory<TestView, TestPresenter<TestView>> the return type's generic is bound to TestPresenter<TestView>. So there is a possible implementation for each subtype of PresenterFactory<...>.
I think the very first part of your problem statement should be addressed as I notice your annotation processor is implementing the raw ViewFactory type. I guess with type erasure, since it's generated code, it doesn't make a real difference in practice. But if the processor could generate implementations using the parameterized type, it would at least be easier to reason about the problem.
So, given a message signature <S extends Presenter<T>> T create(S presenter), you could have it generate:
public class TestViewImplFactory implements ViewFactory<TestView> {
#Override
public <S extends Presenter<TestView>> TestView create(S presenter) { ... }
}
Or more minimally:
public class TestViewImplFactory implements ViewFactory<TestView> {
#Override
public TestView create(Presenter presenter) { ... }
}
But then, with either of those, you cannot restrict the parameter to TestPresenter. You would have to change ViewFactory to something like
public interface ViewFactory<T extends View, U extends Presenter<T>>
and them implement ViewFactory<TestView, TestPresenter>. You kind of have to use the type parameters in the implementation to achieve the type restrictions you want.

How to specify concrete type for abstract method param in Jersey/ Jackson?

I am using Jersey and have exposed a resource Resource which implements an Interface. One of the methods from Interface has a parameter a of type A which is an abstract class.
Here is some code for explanation:
//Interface.java
public interface Interface {
public void setA(A a);
}
//Resource.java
#Path("/hello")
public class Resource implements Interface {
#POST
public void setA(A a){ //Here I want to specify AImpl instead of A
//Code that uses AImpl
}
}
//A.java
public abstract class A{
//Some abstract stuff
}
//AImpl.java
public class AImpl extends A{
//Some concrete stuff
}
This leads to an error:
JsonMappingException: Can not construct instance of A, problem: abstract types can only be instantiated with additional type information
How can this be avoided/ overcome?
One solution would be to make Jersey/Jackson aware that it can use the concrete implementation of A (which is AImpl) in method setA() of Resource. Is there any annotation that I can use to do that?
Have you considered simply making Interface generic? Something like
public abstract class SuperType {}
public class SubType extends SuperType {}
public interface Resource<T extends SuperType> {
Response doSomething(T type);
}
#Path("resource")
public class SubTypeResource implements Resource<SubType> {
#POST
#Override
public Response doSomething(SubType type) {
...
}
}

Java abstract method and interface

I have an interface HTTPSequence. I also have an abstract class AbstractHTTPFactory which in turn has an abstract method returning ArrayList<HTTPSequence>. In classes derived from AbstractHTTPFactory I want to override those methods to return ArrayList<[Class implementing HTTPSequence]>.
Is it possible ? Now compiler gives my an error suggesting that I change overriden methods signature to HTTPSequence.
// abstract class with abstract method returning ArrayList of objects implementing interface
abstract public class AbstractHTTPFactory {
abstract ArrayList<HTTPSequence> make();
}
// Specific class that returns ArrayList of objects of the class implementing HTTPSequence
public class RecipesHTTPFactory extends AbstractHTTPFactory{
public ArrayList<Recipe> make() {
}
}
// interface
public interface HTTPSequence {
}
// one of the classes implementing the above interface
public class Recipe implements HTTPSequence {
}
And the message Eclipse gives me is:
Multiple markers at this line
- The return type is incompatible with AbstractHTTPFactory.make()
- implements ....ider.AbstractHTTPFactory.make
You could write your AbstractClass method to return ArrayList<? extends Interface>, and then you do not have to change the derived class method signatures
The following design would allow you to avoid having to return a wildcarded generic type, which are of limited use to the caller:
abstract public class AbstractHTTPFactory<T extends HTTPSequence> {
abstract ArrayList<T> make();
}
public class RecipesHTTPFactory extends AbstractHTTPFactory<Recipe> {
public ArrayList<Recipe> make() { ... }
}
Now you can call new RecipesHTTPFactory().make() and get back an ArrayList<Recipe> instead of an ArrayList<? extends HTTPSequence>.
Also note that unless the caller specifically expects an ArrayList, it is better for make() to return a List<T>.

Java - Return correct type from Generic method

I have the following class structure:
public class Team {
...
}
public class Event {
}
public abstract class Fixture<T extends Team> implements Event {
...
}
public abstract class Forecast<Event> {
}
public class MyPrediction<T extends Fixture<? extends Team>> extends Forecast<Fixture<? extends Team>>{
}
I am trying to model sports events of all kinds (i.e. a 'Fixture' is for a particular game between two participants play against each other, whereas another type of 'Event' may have many participants), along with predictions for the outcome of particular 'Events'. I have a generic method:
public <T> MyPrediction<Fixture<? extends Team>> getMyPrediction(Fixture<? extends Team> fixture) {
}
I want to be able to return a MyPrediction instance which has the generic type of the fixture argument, but I can't seem to do so. For example, if I do something like the following, then I get a compilation error:
SoccerFixture<EnglishSoccerTeams> soccerMatch = new ScoccerFixture<EnglishSoccerTeams>();
MyPrediction<SoccerFixture<EnglishSoccerTeams>> = getMyPrediction(soccerMatch);
I am willing to change my class structure to incorporate this feature. How can I do so?
Change the signature of getMyPrediction to
public <T extends Fixture<? extends Team>> MyPrediction<T> getMyPrediction(T fixture)
This tells the compiler that the fixture types in the argument and result are the same, allowing type-checking to pass.
Here is a complete example, with some other minor changes to get it to compile. It introduces the class Predictor to hold the getMyPrediction method and a doit method to show sample use:
public interface Team {
}
public interface Event {
}
public abstract class Fixture<T extends Team> implements Event {
}
public abstract class Forecast<T> {
}
public class MyPrediction<T extends Fixture<? extends Team>> extends
Forecast<Fixture<? extends Team>> {
}
public class SoccerFixture<T extends SoccerTeam> extends Fixture<T> {
}
public class SoccerTeam implements Team {
}
public class EnglishSoccerTeam extends SoccerTeam {
}
public class Predictor {
public <T extends Fixture<? extends Team>> MyPrediction<T> getMyPrediction(T fixture) {
return new MyPrediction<T>();
}
public void doit() {
SoccerFixture<EnglishSoccerTeam> soccerMatch = new SoccerFixture<EnglishSoccerTeam>();
MyPrediction<SoccerFixture<EnglishSoccerTeam>> myPrediction = getMyPrediction(soccerMatch);
}
}
As noted elsewhere, you might need to introduce one or more factory objects to perform meaningful work in the MyPrediction implementation.
Java's type system is not powerful enough to do directly what you propose, because of type erasure (the generic parameters are not available at runtime.
The usual solution is to create a separate EventFactory class, which you can then pass in to any method which needs to create a specific Event subtype instance.

Avoiding compiler warning when implementing interface with bounded return type

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.
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;
}
}
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.

Categories

Resources