On Tue, Jun 8, 2010 at 2:24 AM, Tim Boudreau <[email protected]> wrote:

>
> I am simply suggesting that there should be a way to bind Server ->
> AbstractServer -> ServerImpl -> ServerImplSubclass in a single call.
> Whether it is a singleton or has any scope or is @Named is entirely
> orthagonal.
> //allow @Inject Server | AbstractServer | ServerImpl |
> ServerImplSubclass to succeed w/o explicit bind() calls for each type
>
> bindHierarchy(Server.class).annotatedWith(named("public")).to(ServerImpl.class);
>

I'm not certain scope is fully orthogonal.  If ServerImpl is not a singleton
here, the bindHierarchy class can be accomplished by just figuring out the
difference in types between the bindHierarchy(Super) call & the to(Sub)
call, and essentially call bind(SuperN).[annotatedWith(..).].to(Sub) for
every resulting type.  But, if you want to bind the classes to a singleton,
those implicit bind calls would be incorrect, because each one would be
binding to a distinct singleton of ServerImpl.  To fix that, bindHierarchy
could also do a binding of the to(Sub) call in the wanted scope, but that
would have the side effect of possibly breaking a future caller who wanted
to do something like
'bindHierarchy(Server.class).annotatedWith(named("private")).to(ServerImpl.class)
and want a different ServerImpl instance.

If you're willing to manipulate the resulting binding too -- annotate
ServerImpl's binding with named("public") -- things are a lot safer.  Here's
a helper function that can do just that:

<T> bindHierarchy(Class<? extends T> binding, Class<T> topmostParent,
Annotation annotation, Scope scope) {
   //pseudocode:
   Key bKey = Key.get(binding, annotation);
   bind(bKey).in(scope);
   for(Class<?> intrface : binding.getInterfaces()) {
      bind(intrface).annotatedWith(annotation).to(bKey).in(scope);
   }
   while(true) {
      binding = binding.getSuperclass();
      bind(binding).annotatedWith(annotation).to(bKey);
      if(binding == topmostParent)
          break;
    }
 }

If you want to be super safe, you can just specify the binding, annotation &
scope, and take the bound types as a vararg or list.  I've done exactly that
in the past, when I wanted to bind a ScheduledThreadPoolExecutor instance to
Executor, ExecutorService, ScheduledExecutorService, and some other internal
types.

sam


>
> This is just specifying an array of types to bind to the same
> implementation class, while taking advantage of the fact that
> inheritance dictates the contents of that array, so you can specify
> the entire array simply by indicating the head and tail of it.  There
> is no ambiguity since a hypothetical @Inject AbstractServer2 cannot be
> an instance of { Server, AbstractServer, ServerImpl,
> ServerImplSubclass }.
>
> My apologies if my example suggested this had something to do with
> singletons.
>
> The irony of all this being, I generally believe in avoiding deep
> inheritance hierarchies like the plague.  However, if you are writing
> something for other people to extend, your audience is most likely
> people who expect to use inheritance and will be baffled otherwise.
>
> -Tim
>
> --
> 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