Reputation: 7190
I have a method having a generic type T
as argument
private static <T> void doValidation(T[] pArray, int size, String firstName, String secondName) {
...
for (int i = 0; i < size; i++) {
...
validate(pArray[i]);
}
}
And then I have different method given the specific type, such as A
, B
, etc..
private static void validate(A a) {
}
private static void validate(B b) {
}
I would like it to resolve the type in runtime and call the corresponding method based on the type, is it possible?
At the moment I get
no suitable method found for validate(T)
method ValidateDataStructure.validate(A) is not applicable
(argument mismatch; T cannot be converted to A)
method ValidateDataStructure.validate(B) is not applicable
(argument mismatch; T cannot be converted to B)
where T is a type-variable:
T extends Object declared in method <T>doValidation(T[],int,String,String)
----
(Alt-Enter shows hints)
It wants me to cast of course the argument..
I am trying to do a port of Assimp, my intent is to be as much as possible close to the C structure. This is the function I am trying to port right now..
Upvotes: 1
Views: 90
Reputation: 20631
Depending on your exact needs, which aren't totally clear from your question, you have some options.
It seems like you probably don't actually need your doValidation
method to behave differently depending on T
, but rather your validate
method to behave differently depending on the run-time type of its argument. This is a somewhat different problem, but it is easily solvable: the best option is probably to have it delegate to an overridable method, something like:
private static <T extends Validatable> void validate(T arg)
{
arg.validate();
}
(You need to define an appropriate Validatable
interface of course, and the T
type parameter in the doValidation method also needs to be declared as T extends Validatable
).
However, the above option requires that you can modify classes A
and B
(make them implement Validatable
). Another option, not nearly as clean from a design point of view but without this limitation, is to determine the type and dispatch to a different method accordingly, by introducing a validate
method with an Object
argument as follows:
private static void validate(Object arg)
{
if (arg instanceof A) {
validate((A) arg);
}
else if (arg instanceof B) {
validate((B) arg);
}
else {
throw new RuntimeException("Don't know how to validate object of class " + arg.getClass.getName());
}
}
Upvotes: 0
Reputation: 100209
If you want to validate types you cannot extend (e.g. Integer
, String
),
you may implement your own dynamic dispatching. For example, you can create a map of validators like this (Java-8):
private static final Map<Class<?>, Consumer<?>> validators = new HashMap<>();
static {
validators.put(A.class, (A a) -> validate(a));
validators.put(B.class, (B b) -> validate(b));
...
}
And write a selector method:
static <A> Consumer<A> getValidator(Class<A> clazz) {
// do nothing for unknown type
return (Consumer<A>)validators.getOrDefault(clazz, () -> {});
}
Finally you can use it like this:
getValidator(value.getClass()).validate(value);
Upvotes: 1