I am having hard time figuring out how to bind interface to enum using Guice.
public interface Snack {
public int caloriesCount();
}
public enum Chocolate implements Snack {
MILK(20),
DARK(5),
WHITE(10);
private int calCount;
private Chocolate(int calCount) {
this.calCount = calCount;
}
@Override
public int caloriesCount() {
return calCount;
}
}
If I try:
bind(Snack.class).to(Chocolate.class);
I get No implementation for Chocolate was bound
I understand that instead of trying to bind to the enum I should bind to the set of that enum's values, but it defies me how that can be accomplished. Appreciate any hints. Thanks, Maciek
Binding to an enum class like that is impossible, because Guice cannot create its own instance. Here, the default behavior would be to create a new instance of Chocolate
, which doesn't make a lot of sense—every possible instance of an enum must be declared at compile time within the enum itself, and Guice won't pick an arbitrary existing one for you.
You might want to do one of these three things instead:
Bind Snack
to a particular type of Chocolate
.
bind(Snack.class).toInstance(Chocolate.DARK);
Bind Snack
to Chocolate
, and Chocolate
to a particular type of Chocolate
. This is like the above, but now you can ask for Chocolate
directly and get an instance, instead of only being able to ask for a Snack
.
bind(Snack.class).to(Chocolate.class);
bind(Chocolate.class).toInstance(Chocolate.DARK);
Allow developers to inject a Set<Snack>
, which happens to return all Chocolate
instances.
// manual wildcard required so we don't get an ImmutableSet<Chocolate>
Set<Snack> setOfSnacks = ImmutableSet.<Snack>copyOf(Chocolate.values());
// bind a Set<Snack> specifically
bind(new TypeLiteral<Set<Snack>>() {}).toInstance(setOfSnacks);
You can use any Set implementation, but because all toInstance
bindings are implicitly singletons, you can reduce some risk of modification if you use Guava's ImmutableSet
or at least Collections.unmodifiableSet
. If this is close to what you want, you may be interested in learning about the optional Multibindings plugin.
Of course you could also write your own Provider<Set<Snack>>
or a method that @Provides Set<Snack>
, thereby getting a new set instance every time...but if you expect to use this across your app it may make more sense to share one immutable copy.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With