Reputation: 583
Refering to the following code snippet, I have a interface Splitter
which takes generic type parameters T
and V
. There is one implementation which is CompanySplitterImpl
. There could be many such implementations.
public interface Splitter<T, V> {
V[] split(T arg);
}
public class CompanySplitterImpl
implements Splitter<Company, Department> {
@Override
public Department[] split(Company comp) {
return comp.getDepartment();
}
}
I am trying to write a factory method which returns different implementation based on a key parameter value passed in to the factory method.
// Factory method to return different Implementation of Splitter
// (Is Splitter return type correct?)
public static Splitter getSplitter(String key) {
return new CompanySplitterImpl(); // Is this correct?
}
My question is what is the correct manner of returning instance of different implementation of Splitter<K, V>
?
// Client to call factory method...
// Not sure what will be type argument for Splitter type
Splitter<?> split = getSplitter("dummyKey");
At the client side, What will be the type argument for Splitter type?
Upvotes: 1
Views: 247
Reputation: 37645
Splitter
is a raw type. You should not use raw types. Since the key (a String
) carries no type information, it is not possible to infer the type parameters from the argument passed to getSplitter
. Therefore, the only way to avoid raw types is to make the return type Splitter<?, ?>
.
This is ugly and forces the caller of the method to cast:
Splitter<Company, Department> split = (Splitter<Company, Department>) getSplitter("dummyKey");
A better way of doing this is to use a key that carries type information, and the usual way to do this is to use Class<T>
objects.
public static <T, V> Splitter<T, V> getSplitter(Class<T> key1, Class<V> key2) {
if (key1 == Company.class && key2 == Department.class)
return (Splitter<T, V>) new CompanySplitterImpl();
// more cases
}
Then the caller could do:
Splitter<Company, Department> split = getSplitter(Company.class, Department.class);
Upvotes: 5