I am trying to create a generic Identifier class which I would be able to use as follows:
public class TestGenericIdentifier {
public static void main(String[] args) {
Identifier<Car> carId = new Identifier<>(Car.IdentifierType.LICENSE_PLATE, "123 XYZ");
Identifier<Person> personId = new Identifier<>(Person.IdentifierType.SOCIAL_SECURITY, "123456");
System.out.println(carId);
System.out.println(personId);
}
}
To get there, I started by creating an Identifiable interface:
public interface Identifiable<T extends Enum> {}
The idea being that a class that implements Identifiable needs to provide an enum T in its declaration which is the type of the first parameter of the Identifier constructor:
public class Identifier<E extends Identifiable<T>> { //does not compile
public Identifier(T type, String value) {
//some code
}
}
Now the code above does not compile as I can only use Identifiable (no parameter T) on the first line. If it worked I would be able to write the following two classes:
public class Car implements Identifiable<Car.IdentifierType>{
public enum IdentifierType {
SERIAL_NUMBER,
LICENSE_PLATE;
}
}
public class Person implements Identifiable<Person.IdentifierType> {
public enum IdentifierType {
DATABASE_ID,
SOCIAL_SECURITY;
}
}
Is there a way to do that using generics?
EDIT
One way is to compromise conciseness and keep compile-time type checking by doing:
public class Identifier<T extends Enum> {
public Identifier(T type, String value) {
}
}
and the main function becomes:
Identifier<Car.IdentifierType> carId = new Identifier<>(Car.IdentifierType.LICENSE_PLATE, "123 XYZ");
Identifier<Person.IdentifierType> personId = new Identifier<>(Person.IdentifierType.SOCIAL_SECURITY, "123456");
You can get this to compile by tweaking your code a bit but I’m not sure it’s what you want. The following seems to work for me.
The question is why do you want to do this? If you edit your question some more with the background, I can edit my answer to be more helpful.