Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Guice, how do I inject the super class's constructor parameters? [duplicate]

Possible Duplicate:
Guice with parents

class Book{string title;}
class ChildrensBook extends Book{}
class ScienceBook extends Book{} 

I want to inject book titles into the subclasses, for example, childrensBook should be assigned the title "Alice in Wonderland" and ScienceBook should get "On the Origin of Species". How can I accomplish this with Guice?

(Note that I do not want to overwrite the title field in the subclass)

like image 973
chao luo Avatar asked Jan 26 '12 07:01

chao luo


2 Answers

Previously asked and answered here:

Buried in the Minimize Mutability section of the Guice Best Practices, you'll find this guideline:

Subclasses must call super() with all dependencies. This makes constructor injection cumbersome, especially as the injected base class changes.

In practice, here's how to do it using constructor injection:

public class TestInheritanceBinding {
   static class Book {
      final String title;
      @Inject Book(@Named("GeneralTitle") String title) {
         this.title = title;
      }
   }
   static class ChildrensBook extends Book {
      @Inject ChildrensBook(@Named("ChildrensTitle") String title) {
         super(title);
      }
   }
   static class ScienceBook extends Book {
      @Inject ScienceBook(@Named("ScienceTitle") String title) {
         super(title);
      }
   }

   @Test
   public void bindingWorked() {
      Injector injector = Guice.createInjector(new AbstractModule() {
         @Override protected void configure() {
            bind(String.class).
            annotatedWith(Names.named("GeneralTitle")).
            toInstance("To Kill a Mockingbird");
            bind(String.class).
            annotatedWith(Names.named("ChildrensTitle")).
            toInstance("Alice in Wonderland");
            bind(String.class).
            annotatedWith(Names.named("ScienceTitle")).
            toInstance("On the Origin of Species");
         }
      });
      Book generalBook = injector.getInstance(Book.class);
      assertEquals("To Kill a Mockingbird", generalBook.title);
      ChildrensBook childrensBook = injector.getInstance(ChildrensBook.class);
      assertEquals("Alice in Wonderland", childrensBook.title);
      ScienceBook scienceBook = injector.getInstance(ScienceBook.class);
      assertEquals("On the Origin of Species", scienceBook.title);
   }
}
like image 66
Jeff Axelrod Avatar answered Oct 26 '22 22:10

Jeff Axelrod


Your best bet would probably be writing the subclass constructors with different parameter annotations -- something like

class ChildrensBook extends Book {
  @Inject ChildrensBook (@AliceInWonderland String title) {
     super(title);
  }
}
like image 24
Louis Wasserman Avatar answered Oct 27 '22 00:10

Louis Wasserman