Is it acceptable practice to put generics on an interface when the implementation will not be generic? Lets say that my project will have many classes that read data from the database. I may make a generic interface like:

public interface DataRetriever<T, R>{

  R retrieveData(T criteria);

}

public class UserDataRetriever implements DataRetriever<UserCriteria, User>{

  @Override
  public User retrieveData(UserCriteria criteria) {
    ...
  }
}

Or another example might be:

public interface DataRetriever2<R>{

  R retrieveData();

}
public class UserDataRetriever2 implements DataRetriever2<User>{

  @Override
  public User retrieveData() {
    ...
  }
}

With having generics on interfaces, it looks like I can get way more re-usability out of my interfaces and don't need one interface per data retrieval class. However, I have concerns that the documentation for my interface is forced to be vague. People also have to adhere to the number of parameters on the retrieveData method so they might be creating a new pojo object for scenario 1 or might be forced to put everything in the constructor in scenario 2. Thoughts on using generics here when the implementation will not use generics?

up vote 2 down vote accepted

It's common practice to have non-generic implementations of generic interfaces, just the way you showed it, and there's nothing wrong with it.

But of course, designing a good generic interface is a bigger challenge than a specific one. So, you have to decide what a DataRetriever instance is to be and what operations it has to support to be useful. I'd expect a single DataRetriever instance to manage all the querying of a given class, e.g. User, (but maybe that's not what you have in mind...).

Then, R retrieveData(T criteria) seems like a useful operation to me, whereas R retrieveData() lacks a way of specifying the query criteria.

Maybe you'll also want to introduce a generic interface for QueryCriteria and have T extend QueryCriteria<R>, so every implementation expects criteria that match the object type.

People also have to adhere to the number of parameters on the retrieveData method so they might be creating a new pojo object for scenario 1 or might be forced to put everything in the constructor in scenario 2.

Adhering to the function signature is at the core of using interfaces, so define it in a way that your colleages aren't forced to fall back to work-arounds, otherwise you should re-think your interface. So, if the result of your analysis is that for data retrieval a single criteria object is all that's needed, stick to that pattern (and let the various implementations define the criteria classes they need).

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.