You can bind A to B if B is a subtype of A. If you want to bind A to A
explicitly, simply write:
bind(A.class).in(...);
>
> According to my little tests, the first case doesn't seem to be
> possible and I'd like to petition to enable just that. The rationale
> is simple - the client code should not know when the injected class is
> an interface or a concrete class because it makes no difference to the
> user anyway. It's good practice to separate an implementation from its
> interface, but there's no reason to enforce this practice in the
> binding DSL
I dont follow--
Are you suggesting we get rid of the static typing in bindings?
How does it matter if client code knows/cares about whether a member
variable is concrete or abstract? Isn't that the point of Dependency
Injection?
Also, with
> the new versions of the Mock frameworks, one can easily mock a
> concrete class anyway, so in effect, duck typing is proved to easily
> achievable with Java 1.5.
Duck typing is not available in Java except via contortions like
reflection. Mocking is not duck typing, duck typing typically means
two things:
- evaluating types in expressions at runtime (dynamic typing)
- resolving dispatch at runtime by lexical similarity
Java does neither of these (though I hear a bytecode instruction to
facilitate the latter may be coming in 7's JVM).
Dhanji.
> You can bind A to B if B is a subtype of A. If you want to bind A to A
> explicitly, simply write:
>
> bind(A.class).in(...);
>
Ah that's the hack I'm looking for.
> I dont follow--
> Are you suggesting we get rid of the static typing in bindings?
Yes and no. This needs to be discussed a little more I guess. There
are 2 issues here.
1) The DSL usability problem. In English, the word "bind" is usually
bound to a proposition "to" (pun intended), so if you say
bind(A.class).in(...), it's a little weird and not particularly
intuitive.
2) I can imagine in the course of re-factoring old code to take
advantage of Guice, there would be some existing decorator/proxy/
facets that are wrapping some ugly old code. It would be nice if
bind(A.class).to(B.class) works, where A and B have no immediate
parent child relationship whatsoever. I know provider already enables
this, but that's 1 more layer of code. The anonymous class syntax is
ugly and a top level provider class is just even more code in more
disparate places that doesn't really enable a reuse.
> How does it matter if client code knows/cares about whether a member
> variable is concrete or abstract? Isn't that the point of Dependency
> Injection?
It doesn't, that's what I'm saying.
> Duck typing is not available in Java except via contortions like
> reflection. Mocking is not duck typing, duck typing typically means
> two things:
>
> - evaluating types in expressions at runtime (dynamic typing)
> - resolving dispatch at runtime by lexical similarity
>
> Java does neither of these (though I hear a bytecode instruction to
> facilitate the latter may be coming in 7's JVM).
No contention here. My use of the term duck typing is abusive. I
actually mean programming to an interface without explicitly having to
extract a static interface.
> except it's not really a 'hack' - it's more like DRY (don't repeat yourself)
> because
> there's no point in mentioning A.class twice if you're just going to bind it
> to itself.
> also, if you @Inject A (where A is a concrete class) and don't supply any
> explicit
> bindings, Guice will inject an instance of A - so allowing bind(A.class).to(
> A.class)
> doesn't add much value, as that's actually the default if no bindings for A
> are given.
I would actually argue that it makes the code more explicit and clear
by saying binding A to A. Just bind A without specifying it's
destination and hoping that it would automagically bind to itself is
like asking calling your girlfriend up and hope that she will pick up
your laundry by not saying a single word.
Ok there's an issue of scope
here but still, just a thought.
> bind(A.class).in(...) is just shorthand for bind(A.class).to(A.class
> ).in(...)
> imho this is just as understandable (like in English can't => can not)
I'd agree with you on the short hand part if
bind(A.class).to(A.class).to(...) works as well as
bind(A.class).in(..). But bind(A.class).to(A.class) gives me an error
saying "Binding points to itself", which is apparently allowed by
magic. All this conversation really boils down to the fact that I
think bind(A.class).to(A.class) should just work.
> but for the old code to accept an instance of B in place of A where there's
> no relationship between A and B then there needs to be some proxying -
> and in a lot of cases this is non-trivial and can't be automated (so using a
> Provider to explicity proxy it would be preferable and much safer)
>
> even in those cases where it could be automated it would be better to do
> this outside of the core in a support library, which would be possible with
> issue 49 (http://code.google.com/p/google-guice/issues/detail?id=49)
It might be advantageous if there were methods such as
bind(A.class ).toInstanceMethod(B.class).giveMeAnA([params]), and
bind(A.class).toStaticMethod(B.class).giveMeAnA([params]), where
giveMeAnA() is an actual method that belongs to A.
The two methods I
mentioned would have the signature of <T> T toInstanceMethod(Class<T>
cls), and <T> T toStaticMethod(Class<T> cls), and the cls param does
not have to have any parent child relationship with A. The reason this
is useful is because there are many cases where changing B's
implementation is not desirable or even possible.
toInstanceMethod
will have the additional constraint that B must have a default
constructor or an injectable constructor
. annotatedWith() will not be
support in these 2 new methods because that assumed the user has or
will change the implementation of B by adding Guice annotations, which
defeats the purpose of the 2 methods. But then of course, I do realize
the returned object of type T in these 2 methods will have to be
mangled with some convoluted proxy or some code generator.
--
Cheers, Stuart
Yeah the fact that bind(A.class).to(A.class) doesn't work really
throws me off. Should file a bug for this?
Yes B is sort of a provider that provides A, the problem is that there
are cases where users have no control of the implementation of B but
still want to take advantage of the juiciness of Guice.
I don't have a particular reason against implementing the 2 methods in
a legacy support library. That library may very well just consist of a
LegacySupportBindingBuilder that supports the 2 methods and hide
AnnotatedBindingBuilder, and a AbstractLegacySupportModule that gives
you that LegacySupportBindingBuilder. File for an enhancement?