48

I have this class:

public class House {
    private final Door door;
    private final Window window;
    private final Roof roof;

    @Inject
    public House(Door door, Window window, Roof roof) {
        this.door = door;
        this.window = window;
        this.roof = roof;
    }
}

Where Door, Window and Roof are concrete classes. Now if I want to implement a Module for this scenario, I would do it like this:

public class HouseModule extends AbstractModule {
    @Override
    protected void configure() {
        bind(Door.class).to(Door.class);
        bind(Window.class).to(Window.class);
        bind(Roof.class).to(Roof.class);
    }
}

But I wonder if this is the right way to bind concrete classes, or if there are easier ways. I feel there is an easier way to this.

Dharman
  • 30,962
  • 25
  • 85
  • 135
helpermethod
  • 59,493
  • 71
  • 188
  • 276
  • You should submit your own solution as answer and accept that one. It's the best answer from the list. No module is needed at all, not even an empty one. – Benny Bottema Jul 28 '19 at 20:18

3 Answers3

58

This is the way to go:

protected void configure() {
    bind(Door.class);
    bind(Window.class);
    bind(Roof.class);
}

Since they are concrete classes, as Guice says, you can't bind them to themselves :-)

Check out the Binder docs, it notes:

bind(ServiceImpl.class);

This statement does essentially nothing; it "binds the ServiceImpl class to itself" and does not change Guice's default behavior. You may still want to use this if you prefer your Module class to serve as an explicit manifest for the services it provides. Also, in rare cases, Guice may be unable to validate a binding at injector creation time unless it is given explicitly.

Concrete classes with constructor marked as @Inject are automatically available for injection. But it helps the developer (you) know what is configured in the module.

Community
  • 1
  • 1
Jalayn
  • 8,934
  • 5
  • 34
  • 51
  • Really confused - does "automatically available in modules" mean to all modules in your project globally? Or is it aware of the package-local module or does it match up based on module names or something? – djechlin Dec 05 '14 at 22:42
  • It just means that you should not even have to indicate how to to the binding since Door, Window and Roof are concrete classes. They are available in all modules. If you have different implementations of a given interface, THEN you have to help Guice. – Jalayn Dec 08 '14 at 15:41
  • You don't need a module when you have no need to bind an interface to a class. – Noya Aug 20 '15 at 10:11
  • "Available in modules" is a bit of a confusing phrase - the `@Inject` annotation means a class is automatically available *for injection*. – dimo414 May 04 '17 at 20:59
31

Guice's Just-In-Time binding does exactly what you want. Given your Door, Window and Roof meet following requirements (quoted from the Guice documentation):

either a public, no-arguments constructor, or a constructor with the @Inject annotation

an empty Module implementation will be sufficient:

public class HouseModule extends AbstractModule {
    @Override
    protected void configure() {
    }
}
Brendon Dugan
  • 2,138
  • 7
  • 31
  • 65
edwardw
  • 12,652
  • 3
  • 40
  • 51
  • Where does the empty module go? How does Guice know to relate them? – djechlin Dec 05 '14 at 23:14
  • @djechlin This'll depend on how your application is configured. For instance, a [Play](https://www.lightbend.com/play-framework) based application will expect such a module file to be in the root package, or configurable via `play.modules.enabled` in the application.conf – Siddhartha Nov 10 '17 at 04:53
6

Binding is needed to link Interface and Implementation class (to change to other implementation in test env for example). But since you have concrete classes, no need for binding to, just bind classes

korifey
  • 3,379
  • 17
  • 17