> 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.

Reply via email to