2010-11-30 4 views
8

또한 주입 가능한 부모 생성자를 호출해야 할 때 Guice와 어떻게해야합니까? 예 : 나는 모든 파생 된 자식에 의해 공유 된 객체로 주입되는 생성자를 가진 추상 부모 클래스를 가지며 각 자식에도 주사 가능한 생성자가 있습니다.Guice with parents

Java는 내가 Guice가 삽입하지 않고 paremeter로 객체를 전달하기를 원하기 때문에 super()를 호출하면 작동하지 않습니다.

감사

편집

는 : 어쩌면 내가 대신 방법의 주사를 사용해야 할 경우 궁금?

답변

9

Guice를 사용하지 않았다면 똑같은 작업을해야합니다 ... 부모 생성자가 각 하위 생성자의 매개 변수로 필요한 매개 변수를 선언하고이를 모두 super으로 전달합니다.

당신의 추상적 인 부모 클래스의 생성자는 Foo, 자식 클래스의 생성자는 같이해야합니다 그래서 경우 : Guice 모범 사례의 Minimize Mutability 섹션에 묻혀

@Inject public ChildClass(Foo foo, Bar bar) { 
    super(foo); 
    this.bar = bar; 
    ... 
} 
+0

나중에 코드에서 ChildClass를 구성해야하는 경우 어떻게해야합니까? 그렇게하는 가장 좋은 방법은 무엇입니까? ChildClass와 마찬가지로 child = 새 ChildClass (새 Foo(), bar)? Foo도 주사를 맞으면 어떨까요? – lapkritinis

4

을,이 가이드 라인을 확인할 수있는 것들 :

하위 클래스는 모든 종속성이있는 super()을 호출해야합니다. 이로 인해 생성자 주입이 번거로 웠습니다. 특히 주입 된베이스가 인 것처럼 변경되었습니다. 실제로

, 여기에 생성자 주입을 사용하여 수행하는 방법은 다음과 같습니다

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); 
    } 
} 
1

더 나은 대안은 슈퍼 클래스가 주입하고자하는 모든 필드를 캡슐화 전략 패턴에 비슷한 것을 사용하는 것입니다, 다음 하위 클래스가이를 주입 할 수 있습니다. 예 :

public abstract class Animal { 
    /** 
    * All injectable fields of the Animal class, collected together 
    * for convenience. 
    */ 
    protected static final class AnimalFields { 
    @Inject private Foo foo; 
    @Inject private Bar bar; 
    } 

    private final AnimalFields fields; 

    /** Protected constructor, invoked by subclasses. */ 
    protected Animal(AnimalFields fields) { 
    this.fields = fields; 
    } 

    public Foo getFoo() { 
    // Within Animal, we just use fields of the AnimalFields class directly 
    // rather than having those fields as local fields of Animal. 
    return fields.foo; 
    } 

    public Bar getBar() { 
    return fields.bar; 
    } 
} 

public final class Cat extends Animal { 
    private final Whiskers whiskers; 

    // Cat's constructor needs to inject AnimalFields to pass to its superclass, 
    // but it can also inject whatever additional things it needs. 
    @Inject 
    Cat(AnimalFields fields, Whiskers whiskers) { 
    super(fields); 
    this.whiskers = whiskers; 
    } 

    ... 
}