37

I need to bind one class as implementation of two interfaces. And it should be binded in a singleton scope.

What I've done:

bind(FirstSettings.class).
    to(DefaultSettings.class).
    in(Singleton.class);
bind(SecondSettings.class).
    to(DefaultSettings.class).
    in(Singleton.class);

But, obviously, it leads to creation of two different instances, because they are binded to the different keys.

My question is how can I do that?

Pavel
  • 1,019
  • 2
  • 10
  • 19

3 Answers3

67

Guice's wiki has a documentation about this use case.

Basically, this is what you should do:

// Declare that the provider of DefaultSettings is a singleton
bind(DefaultSettings.class).in(Singleton.class);

// Bind the providers of the interfaces FirstSettings and SecondSettings
// to the provider of DefaultSettings (which is a singleton as defined above)
bind(FirstSettings.class).to(DefaultSettings.class);
bind(SecondSettings.class).to(DefaultSettings.class);

There is no need to specify any additional classes: just think in terms of Providers and the answer comes rather naturally.

Olivier Grégoire
  • 33,839
  • 23
  • 96
  • 137
4

The solution, I've found is:

bind(FirstSettings.class).
    to(DefaultSettings.class).
    in(Singleton.class);
bind(SecondSettings.class).
    to(FirstSettings.class).
    in(Singleton.class);

It works in my case, because SecondSettings extends FirstSettings.

Pavel
  • 1,019
  • 2
  • 10
  • 19
  • 1
    Works only if SecondSettings is a subclass,subinterface of FirstSettings. There are solutions for this case and others where no link exist between FirstSettings and SecondSettings. – Olivier Grégoire Jan 25 '11 at 10:43
2

So, DefaultSettings is an implementation of both the FirstSettings and SecondSettings, ie:

public class DefaultSettings implements FirstSettings, SecondSettings
{
}

Let's say you have a class EngineA and EngineB

public class EngineA
{
    @Inject
    private FirstSettings settings;
}

public class EngineB
{
    @Inject
    private SecondSettings settings;
}

and you would like to inject the same implementation.

You can declare an interface DefaultSettingsInterface

public interface DefaultSettingsInterface extends FirstSettings, SecondSettings
{
}

and make the DefaultSettings implement DefaultSettingsInterface

public class DefaultSettings implements DefaultSettingsInterface
{
}

Then the configuration may be:

bind(FirstSettings.class).to(DefaultSettingsInterface.class);
bind(SecondSettings.class).to(DefaultSettingInterface.class);
bind(DefaultSettingsInterface.class).to(DefaultSettings.class).in(Singleton.class);
Pavel
  • 1,019
  • 2
  • 10
  • 19
Boris Pavlović
  • 63,078
  • 28
  • 122
  • 148
  • 1
    Thanks, Boris! I believe your solution works! I've just found another way by myself: bind(FirstSettings.class). to(DefaultSettings.class). in(Singleton.class); bind(SecondSettings.class). to(FirstSettings.class). in(Singleton.class); It seems it works too. What do you think? – Pavel Jan 25 '11 at 10:23
  • 1
    I could not know that FirstSettings extends SecondSettings. In that case it's valid and much shorter. Post your solution as an answer and after some time promote it as the best one :) – Boris Pavlović Jan 25 '11 at 10:30
  • Yes, that's true. My fault, I didn't mention that :) – Pavel Jan 25 '11 at 10:37
  • Pavel, your solution works only if you have FirstSettings extend/implement SecondSettings. Also, this solution looks like boilerplate where guice offers simple and elegant solutions. – Olivier Grégoire Jan 25 '11 at 10:39