Google guice uses new TypeLiteral<C<T>>() {}
to overcome the fact that we cannot use C<T>.class
.
Now it is common to the following:
bind(new TypeLiteral<C<T>>() {}).to(MyCSubclassTypedToT.class);
Imagine a different scenario however. We have a generic interface, that we want to inject and the implementation we have is be provided by a generic class.
Guice allows you to do this like this:
bind(new TypeLiteral<MyGenericInterface<T>>() {}).to(new TypeLiteral<MyGenericClass<T>>() {});
Another way of doing this would be to extend MyGenericClass like this:
MyTypedClass extends MyGenericClass<T>
and then bind it like this:
bind(MyGenericInterface<T>>() {}).to(MyTypedClass.class);
If MyGenericInterface is injected a lot (albeit with different types), and every time I do inject it I use MyGenericClass, the latter approach leads to overly verbose code. Hence I'm leaning towards using the former.
I would be very keen to hear other peoples opinion about the use of a TypeLiteral in the to clause of a guice binding. I'm afraid that I might a bit to short sited and thus don't see the pitfalls of this approach.
In this case, using a TypeLiteral
for the generic implementation strikes me as being much better.
Let me phrase it this way: "Would the subclass MyTypedClass
exist if you weren't using Guice?". An essential guideline of Guice is: you shouldn't have to alter your implementation classes to fit the DI framework (well, with the exception of things like the @Inject
annotation).
And what do you gain from subclassing the concrete-yet-generic class? One big loss is that you have to duplicate MyGenericClass's constructor in all the subclasses. All in all, it seems like extra code without much gain.
All-in-all, there's generally nothing wrong with using a TypeLiteral
. And if it's in the .to(...)
portion of the binding clause (as opposed to bind(...)
, it won't even affect the publicly-visible portion of your Module
's bindings, so I don't think there's much to worry about.
There are usually two scenarios:
MyGenericInterface
to MyGenericClass
MyGenericInterface
base on its typeFor the first scenario, bind(MyGenericInterface).to(MyGenericClass);
will be enough, simper and easier to understand.
For the 2nd scenario, you will need to bind implementation of a specific class to a specific implementation, which TypeLiteral will come into play.
Furthermore, the code in your question is not clear that whether T
is a actual class, or a generic type. If it's a generic type,
bind(new TypeLiteral<MyGenericInterface<T>>() {}).to(new TypeLiteral<MyGenericClass<T>>() {});
and
MyTypedClass extends MyGenericClass<T>
won't compile, as some actual class is not provided.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With