Reputation: 135
I'm having a problem properly implementing generics in abstract classes that need to be overridden.
public abstract class AbstractSerachView {
DataStore<AbstractCriteria, AbstractResults, AbstractService> resultsStore;
public abstract DataStore<AbstractCriteria, AbstractResults, AbstractService> getResultsStore();
}
the child clases is as follows:
public class TravelSearchView extends AbstractSearchView {
DataStore<TravelCriteria, TravelResults, TravelService> resultsStore;
public DataStore<TravelCriteria, TravelResults, TravelService> getResultsStore() {
return resultsStore;
}
}
This sort of abstraction does not work at all, although it would be greatly appreciated if I could get this work in some way. What is the correct approach here? I have very little experience with generic types.
The problem is that Eclipse indicates an error in the child class: The return type is incompatible with AbstractSearchView.getResultsStore()
Furthermore, if I leave the child class get method with the 3 abstract types, and override the variable with the 3 travel types, everything is okay except for the return line, where Eclipse indicates: Type mismatch: Cannot convert from DataStore to DataStore
Upvotes: 2
Views: 428
Reputation: 45576
The best way to do it is to make a base class ( or interface ) generic:
public abstract class AbstractSerachView<
TCriteria extends AbstractCriteria>,
TResults extends AbstractResults,
TService extends AbstractService>
{
DataStore<TCriteria, TResults, TService> resultsStore;
public DataStore<TCriteria, TResults, TService> getResultsStore()
{
return resultsStore;
}
}
Then in implementation just provide concrete types
public class TravelSearchView
extends AbstractSearchView<TravelCriteria, TravelResults, TravelService>
{
}
Also, as you can see, implementation class does not need to override getResultsStore
method.
Upvotes: 4
Reputation: 6887
Your AbstractSearchView
class needs to specify generic parameters for each of the parameters of DataStore
if you want to override getResultsStore()
with a different return type.
public abstract class AbstractSearchView<C extends AbstractCriteria, R extends AbstractResults, S extends AbstractService> {
DataStore<AbstractCriteria, AbstractResults, AbstractService> resultsStore;
public abstract DataStore<AbstractCriteria, AbstractResults, AbstractService> getResultsStore();
}
public class TravelSearchView extends AbstractSearchView<TravelCriteria, TravelResults, TravelService> {
DataStore<TravelCriteria, TravelResults, TravelService> resultsStore;
public DataStore<TravelCriteria, TravelResults, TravelService> getResultsStore() {
return resultsStore;
}
}
The supertype bounds (X extends SomeClass
) in the parameters of AbstractSearchView
ensures that subclasses of AbstractSearchView
may only use subtypes of each of those parameters.
Upvotes: 4
Reputation: 198043
Here are your alternatives:
a) Change the superclass type signature to
public DataStore<? extends AbstractCriteria, ? extends AbstractResults, ? extends AbstractService> getResultsStore();
b) Add the type parameters to the class as a whole:
abstract class AbstractSearchView<
C extends AbstractCriteria,
R extends AbstractResults,
S extends AbstractService>
public abstract DataStore<C, R, S> getResultsStore();
}
class TravelSearchView extends AbstractSearchView<
TravelCriteria, TravelResults, TravelService> {
...
}
The issue is that DataStore<TravelCriteria, TravelResults, TravelService>
is not a subtype of DataStore<AbstractCriteria, AbstractResults, AbstractService>
, even if those generic type arguments are respectively subtypes.
Upvotes: 3