This class displays informations:
// display line numbers from a file
display(getLineNumber(myFile));
// display users from DB
display(getUsersName(myDBRepository));
etc...
I wanted to make a generic interface, so I can externalize the code that display information.
Then I could do something like:
myInformationElements.stream().forEach(e -> display(e.getValue());
Here is what I have so far (not working):
public interface InformationElement {
public <T> String getValue (T param);
}
public class NbFileLineInformationElement implements InformationElement{
@Override
public <File> String getValue(File param) {
return *same code as in getLineNumber(myFile)*;
}
}
public class UserInformationElement implements InformationElement{
@Override
public <UserRepository> String getValue(UserRepository param) {
return *same code as in getUsersName(myDBRepository)*;
}
}
- Here my generic type is not working: File is not reconize as java.io.File (same for my jpa repository) What am I doing wrong here ?
- Is this the best practice for my needs ?
You've defined type parameters
File
andUserRepository
that are shadowing the class namesFile
andUserRepository
. This is one of the surprises of naming type parameters the same as existing classes. The type parameters don't represent the classes, and they don't have bounds, so the compiler can only assume they haveObject
methods.This is not the best practice. When implementing generic methods, the methods must remain generic and at least as wide-open with respect to bounds. To be able to restrict what the type parameter means later, define it on the class/interface, and let subclasses supply what it's supposed to mean for that specific implementation with a type argument.
The best solution here is to move InformationElement
's type parameter to the class, and to supply type arguments in your subclasses. The methods are no longer generic, but they do use the type parameters defined on the interface/classes.
interface InformationElement<T> {
public String getValue (T param);
}
class NbFileLineInformationElement implements InformationElement<File>{
@Override
public String getValue(File param) {
return /*same code as in getLineNumber(myFile)*/;
}
}
class UserInformationElement implements InformationElement<UserRepository>{
@Override
public String getValue(UserRepository param) {
return /*same code as in getUsersName(myDBRepository)*/;
}
}