I have a List
that uses a wildcard as follows :
List<DataLink<? extends Context>> dataLinks = new ArrayList<>();
dataLinks.add(new ContextDataLink());
dataLinks.add(new SomeOtherContextDataLink());
I want to be able to iterate through this List
and call the retrieve
method on each element :
Context context = new SomeOtherContext();
for(DataLink<? extends Context> dataLink : dataLinks) {
System.out.println(dataLink.retrieve(context));
}
However, I get the following compiler error in the println
statement :
The method
retrieve(capture#3-of ? extends Context)
in the type>DataLink<capture#3-of ? extends Context>
is not applicable for the arguments >(Context)
Is there a way to achieve the above objective? It doesn't necessarily have to use generics but I feel that using generics would allow me to prevent explicit casting
I went through some answers on SO and understand why this error occurs. However, I am unable to find a solution to resolve it. I understand that I can write a method to capture the wildcard but this doesn't seem to resolve the problem as well :
public static <T extends Context> void retrieve(List<DataLink<T>>
dataLinks,T context) {
for(DataLink<T> dataLink : dataLinks) {
dataLink.retrieve(context);
}
}
When I call the above retrieve method, I get the following compilation error :
The method
retrieve(List<DataLink<T>>, T)
in the type MyClass is not >applicable for the arguments >(List<DataLink<? extends Context>>, Context)
Following is the defintion of the Context
, SomeOtherContext
, DataLink
implementations :
static class Context {
public String doContextThings() {
return "contextThings";
}
}
static class SomeOtherContext extends Context {
public String doSomeOtherContextThings() {
return "someOtherContextThings";
}
}
interface DataLink<T extends Context> {
public String retrieve(T context);
}
static class ContextDataLink implements DataLink<Context> {
@Override
public String retrieve(Context context) {
return context.doContextThings();
}
}
static class SomeOtherContextDataLink implements
DataLink<SomeOtherContext> {
@Override
public String retrieve(SomeOtherContext context) {
return context.doSomeOtherContextThings();
}
}
Note : A solution that doesn't involve generics is the most straightforward solution where the DataLink
class is modified to not take a type parameter and always take a Context
as the parameter type for the retrieve
method. Here, subclasses would cast the Context
to whatever type they are expecting it to be. However, the question remains the same Is this considered bad design or is casting acceptable in such cases?
Aucun commentaire:
Enregistrer un commentaire