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.
