I'm currently exploring Guice capabilities and faced a strange behaviour - when I declare variable as
@Inject
@Named("dragon")
Dragon dragon2;
injection works as expected, but when I want to declare dragon2 as interface (it implements Creature), i. e.
@Inject
@Named("dragon")
Creature dragon2;
I get an error
No implementation for warlock.rincewind.creatures.Creature annotated with @com.google.inject.name.Named(value=dragon)
was bound.
Here's my provider method:
@Named("dragon")
@Provides
public Dragon providesDragon() {
Dragon d = new Dragon("Morkeleb");
return d;
}
I know, there are lots of different ways to overcome this (the simplest one is change provides return type to Creature) but I'm trying to get the reason for such limitation.
Consider, for example:
interface Creature { }
class Dragon implements Creature { }
class Dog implements Creature { }
public class Kennel {
@Inject @Named("foo") Creature c;
}
public class KennelModule extends Abstract Module {
@Override
protected void configure() {
bind(Dragon.class).annotatedWith(Names.named("foo"));
bind(Dog.class).annotatedWith(Names.named("foo"));
}
}
How would your injection know whether to bind Dragon
or Dog
here?
It can't! Injection keys are not covariant. What you need to do instead is, specify the subclass that you want to inject, and bind it to the interface or superclass that you are injecting to. In other words:
public class KennelModule extends Abstract Module {
@Override
protected void configure() {
bind(Creature.class).annotatedWith(Names.named("foo").to(Dragon.class);
}
}
This will give you the behavior you want. You can also still bind injections for Dragon
specifically, of course.
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