Actually once you grok that everything in Guice is key-based and not class
based, a world of clarity opens up =)

In that regard I believe we have one of the best balanced APIs between
flexibility and correctness. I certainly understand, however that this may
not be your first reaction upon uncovering this Guice property.

Dhanji.

On Sun, Jun 6, 2010 at 11:48 PM, Tim Boudreau <[email protected]> wrote:

> > 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]<google-guice%[email protected]>
> .
> For more options, visit this group at
> http://groups.google.com/group/google-guice?hl=en.
>
>

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