Google guice の @ImplementedBy に対して、筆者は使用を避けてきた。
なぜなら、インターフェース宣言でこの @ImplementedBy( 実装クラス名.class ) は、
Injector (com.google.inject.Injector) で、約束する Module(com.google.inject.Module)で、
@ImplementedBy で指定した別のクラスをbind定義することが許されてしまい、@ImplementedBy の
実装クラスを指定する意味が完全に約束されない書き方が存在するからである。
例)
@ImplementedBy(AlogicImpl.class) public interface Alogic{ }
public AlogicImpl implements Alogic{ }
@Inject Alogic logic;
確かに、Alogic は、これでも、以下のように、Module で Alogic に対する AlogicImpl のbind定義、
binder().bind(Alogic.class).to(AlogicImpl.class);
を書かなくても、@Inject Alogic logic に対して、AlogicImpl は、インジェクトされる。
Injector injector = Guice.createInjector(new AbstractModule(){ @Override protected void configure(){ } });
でも、Alogic で、@ImplementedBy(AlogicImpl.class) と書いておきながら、
public BlogicImpl implements Alogic{ }
Injector injector = Guice.createInjector(new AbstractModule(){ @Override protected void configure(){ binder().bind(Alogic.class).to(BLogicImpl.class); } });
は、コンパイルエラーにはならず、許されて BLogicImpl がインジェクトされるのである。
元々、interface と実装は、1対1の関係に限定するものではないし、1対1の場面もあれば、
1対nを許容しなければ何のために interface を定義するのか、無意味になってしまう。
@ImplementedBy( 実装クラス名.class ) と書いて、
Guice の Module でのバインドを省略できるのは、便利なような気もするけど完全に限定できないなら気持ち悪い。