I want to reduce the verbosity of binding a generic interface to several implementations based on TypeLiterals...
I have an interface FieldComputer<T extends ComputeField>
where ComputeField
is my model interface.
Tried extending a ShortLiteral
class (see example below) to reduce the verbosity but it doesn't seem to work. would like to understand why?
// A typical Guice Module
public class ConflationModule implements Module {
// typical overridden configure method
public void configure(Binder binder) {
// Works but is verbose....
bindField_1(binder,
new TypeLiteral<FieldComputer<ComputeFieldImpl>>(){},
FieldComputerImpl.class);
// Doesn't Work
bindField_1(binder,
new ShortLiteral<ComputeFieldImpl>(){},
FieldComputerImpl.class);
// Doesn't Work
bindField_2(binder,
new ShortLiteral<ComputeFieldImpl>(){},
FieldComputerImpl.class);
}
private static class ShortLiteral<CF extends ComputeField> extends TypeLiteral<FieldComputer<CF>>{}
private <CF extends ComputeField> void bindField_1(Binder binder,
TypeLiteral<FieldComputer<CF>> typeLiteral,
Class<? extends FieldComputer<CF>> clazz
) {
binder.bind(typeLiteral).to(clazz);
}
private <CF extends ComputeField> void bindField_2(Binder binder,
ShortLiteral<CF> typeLiteral,
Class<? extends FieldComputer<CF>> clazz
) {
binder.bind(typeLiteral).to(clazz);
}
}
I would suggest you just create TypeLiteral
programmatically, here is an example how to do it with different implementations of one interface:
class TypeLiteralModule extends AbstractModule {
@Override
protected void configure() {
customBind(String.class, StringConsumer.class);
customBind(Integer.class, IntegerConsumer.class);
}
private <T> void customBind(Class<T> clazz, Class<? extends Consumer<T>> impl) {
var typeLiteral = (TypeLiteral<Consumer<T>>) TypeLiteral.get(Types.newParameterizedType(Consumer.class, clazz));
bind(impl).in(Singleton.class);
bind(typeLiteral).to(impl);
}
}
class StringConsumer implements Consumer<String> {
@Override
public void accept(String s) {
}
}
class IntegerConsumer implements Consumer<Integer> {
@Override
public void accept(Integer s) {
}
}