3

Suppose I an abstract class defined like this:

public class Response<T> {
    private List<Response<T>> subResponses;
}

and two subclasses defined like this:

public class SectionResponse extends Response<SectionResponse> {
}

public class FormResponse extends Response<FormResponse> {
}

Basically all subclasses of Response need to have a list of the same class. Now somewhere else in the code I want to have a list of Response objects that can contain either subclass.

What would be the best way to define this list without using raw types? I've tried List<? extends Response<?>> but I can't call the add method on a List defined like this because the parameter is a parameterized type.

assylias
  • 321,522
  • 82
  • 660
  • 783
Sarevok
  • 437
  • 1
  • 7
  • 20

3 Answers3

3

Use the Put-Get-Rule. Namely, return List<? extends Response<?>> but accept List<? super Response<?>> as parameters. Internally you would store the the list as List<Response>

As a note, I would be wary of returning List<? extends Response<?>> on an interface since it can be invasive to the consumer. In most cases the it is better for an interface to nail down the generic type so that you are returning something like List<Response<MyType>> if at all possible.

Community
  • 1
  • 1
Andrew White
  • 52,720
  • 19
  • 113
  • 137
1

Your Response class should be defined like this:

public class Response<T> {
    private List<T> subResponses;
}

So that SectionResponse and FormResponse, as declared, will have a list of themselves.

Now, literally answering your question, for a list that can contain either, you can just have a List<Response<?>>.

However, you likely want more than that -- you probably want to take the elements out of the list and do something to them. If you can be more specific about what you need to be able to do, we can help you further.

newacct
  • 119,665
  • 29
  • 163
  • 224
0

I'll admit I'm not sure exactly what you want to do, but this much works and at least touches on the problem you describe:

public class Response<T extends Response> {
    private List<T> sl = new LinkedList<T>();

    protected void add(T resp) {
        sl.add(this);
    }
}

public class FormResponse extends Response<FormResponse> {
    public FormResponse() {
        add(this);
    }
}
Dolda2000
  • 25,216
  • 4
  • 51
  • 92