Search code examples
guice

Does Guice binding bind subclass as well?


So I have a module which binds an Interface with an implementation class.

bind(ILocalStore.class).to(LocalStore.class);

Will this binding also inject the following constructor:

@Inject
public LocalStoreUser(LocalStore localstore) {
    this.localstore = localstore
}

Solution

  • The injection will work, but not because of the binding.

    Guice treats lookups as if they were a simple Map<Key, Provider> lookup, where Key is composed of a (binding annotation, parameterized type) pair. Guice will not automatically walk up the type hierarchy for you, or otherwise modify the lookup key (checking for a non-annotated or raw type binding, for instance).

    However, if LocalStore has a public no-argument constructor (or an @Inject-annotated constructor as you've listed), Guice can create the type directly, so the code above will work—it just has nothing to do with binding subclasses automatically.


    Consider the following example:

    interface A {}
    interface B extends A {}
    public class C implements B {}
    
    • Without any bindings at all, you could inject C, because it has an implicit public no-arg constructor. The same would apply if C has an @Inject-annotated constructor. Requesting injection of A or B will fail.

    • If you were to bind(A.class).to(C.class) you could inject A (explicit) or C (implicit) but not B. Guice will not bind the subinterface as well, so B has no implementation.

    • Same goes for superclasses/superinterfaces: If you were to bind(B.class).to(C.class) you could inject B (explicit) or C (implicit) but not A, even though B extends A.

    • If you were to bind(A.class).to(B.class) and bind(B.class).to(C.class), then you could inject A, B, or C without repeating yourself.