2010-11-30 5 views
8

注射可能な親コンストラクタを呼び出す必要があるとき、私はGuiceで何をしますか?例えば私はすべての派生子によって共有されるオブジェクトを注入されたコンストラクタを持つ抽象親クラスを持ち、各子も注入可能コンストラクタを持っています。両親とGuice

Javaが私にオブジェクトを渡すことを望んでいるので、super()を呼び出すことはできません。

おかげ

EDIT:多分私は代わりにメソッドインジェクションを使用する必要がある場合、私は疑問に思って?

答えて

9

Guiceを使用していない場合と全く同じことをする必要があります...親コンストラクタが各子のコンストラクタのパラメータとして必要とするパラメータを宣言し、それらをsuperに渡します。だから、

あなたの抽象親クラスのコンストラクタは、子クラスのコンストラクタは次のようになりする必要がある、Fooを取る場合:

Guiceのベストプラクティスの Minimize Mutabilityセクションに埋もれ
@Inject public ChildClass(Foo foo, Bar bar) { 
    super(foo); 
    this.bar = bar; 
    ... 
} 
+0

後でコードでChildClassを構築する必要がある場合はどうなりますか?それを行う最良の方法は何ですか? ChildClassのようにchild = new 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; 
    } 

    ... 
} 
関連する問題