Search code examples
javaoopdependency-injectionguice

Guice - Inject object with two different implementations


First I have to say that I tried googling the answer to this question, but no answer explained my doubts. Anyway, What I'm trying to understand is the following:

public interface Animal{
 public void makeSound(int times);
}

This interface has two different implementations:

public class Cat implements Animal{
 @Override
 public void makeSound(int times){
   for(int=0;i<times;i++){ 
      this.meow();
   }
 }
}

public class Dog implements Animal{
 @Override
 public void makeSound(int times){
   for(int=0;i<times;i++){ 
      this.wolf();
   }
  }
}

I will be using those implementations as in the following example:

public class AnimalStateManager {

 @Inject
 private Animal animal;

 public void makeAnimalAct(){
   animal.makeSound(100)
 }

}

UPDATE 1.1 TO THE POST

And I have one more class using the same "Animal" interface:

 public class AnimalMakeSoundOnce {

     @Inject
     private Animal animal;

     public void makeSoundOnce(){
       animal.makeSound(1)
     }

    }

So my question would be: 1- How I can know what implementation is going to be injected to the AnimalStateManager? 2- What if I wanted to force the "animal" object on the "AnimalStateManager" to be a cat?

UPDATE 1.1 TO THE POST 3- What if I want to make the AnimalMakeSoundOnce uses the Dog implementation and the AnimalStateManager uses the Cat implementation?

Thanks in advance


Solution

  • In Guice you have to implement a module (override the AbstractModule class) and bind Animal to the specific implementation class. To answer your questions:

    1. You can of course call animal.getClass() to check at runtime which implementation class was injected. But this would break the prinziple of IOC where it does not matter which specific implementation you use.

    2. To force animal in your AnimalStateManager be cat you have to write your own Module.

      public class AnimalStateModule extends AbstractModule {
      
          @Override
          protected void configure() {
              bind(Animal.class).to(Cat.class);
          }
      }
      

    And to instantiate the AnimalState:

    Injector inj = Guice.createInjector(new AnimalStateModule());
    final AnimalStateManager ass = inj.getInstance(AnimalStateManager.class);
    ass.makeAnimalAct(); // will cause a call to Cat.meow()