> Just add:
> bind(AImpl.class).in(Scopes.SINGLETON);
> Before the other two bindings. That will solve your problem.
>
> Explanation:
> All bindings in Guice are transitive and resolved by key, so a A ->
Wow, that is stunningly non-intuitive - but it does work, so thank you
very much.
I wonder if something like this should not be supported by the API in
a more obvious way. It makes sense that polymorphism isn't supported
by default - you don't want people to be able to use
@Inject java.lang.Object foo;
and have that work, so I understand the reason it is the way it is.
But it would be nice to just have an API call which looks like:
bindPolymorphic (BaseClass.class, ImplClass.class); //okay, horrible
method name
to bind BaseClass -> Subclass1 -> Subclass2 -> ImplClass
can all be injected without explicit bind calls for each type.
You can *almost* do this in a Module (see terrifying code below), but
with a very non-obvious caveat - you need to request a
Provider<ImplClass> before you bind your own Provider that maps all
supertypes. So the one thing that cannot be injected is ImplClass
itself (otherwise the provider would itself in an endless loop) - you
need an instance of ImplClass, and the ability to reference a
Provider<ImplClass> at bind-time, and the custom Provider must ask
Guice to create it.
I'd imagine this could be supported inside Guice *with* the ability to
inject the actual implementation type too - AFAICT that is not
possible to do inside a Module.
The only thing this does is eliminate the need to have bind() calls
for a list of supertypes, but it would be considerably more intuitive
(*if* it did not have the requirement that the exact type you are
binding cannot be injected):
abstract class BaseModule extends AbstractModule {
protected <T, S extends T> void bindPolymorphic(Class<T> t,
Class<S> mostSpecificSubtype) {
Provider<T> p = new SubtypeProvider<T, S>(t,
mostSpecificSubtype);
Class<? super S> x =
mostSpecificSubtype.getSuperclass(); //CANNOT BIND S ITSELF!
do {
bind((Class<T>) x).toProvider(p);
x = x.getSuperclass();
} while (isType(t, x));
if (t.isInterface()) {
bind(t).toProvider(p);
}
}
private class SubtypeProvider<T, S extends T> implements
Provider<T> {
private final Provider<S> internalProvider;
private S s;
SubtypeProvider(Class<T> type, Class<S>
mostSpecificSubtype) {
internalProvider = getProvider(mostSpecificSubtype);
}
@Override
public synchronized T get() {
return s == null ? (s = internalProvider.get()) : s;
}
}
--
You received this message because you are subscribed to the Google Groups
"google-guice" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/google-guice?hl=en.