Injecting a factory for generics

1,440 views
Skip to first unread message

Chris Conway

unread,
Sep 27, 2010, 10:58:34 AM9/27/10
to google-guice
The following code is an example of a factory that produces a `Bar<T>`
given a `Foo<T>`. The factory doesn't care what `T` is: for any type
`T`, it can make a `Bar<T>` from a `Foo<T>`.

import com.google.inject.*;
import com.google.inject.assistedinject.*;

class Foo<T> {
public void flip(T x) { System.out.println("flip: " + x); }
}

interface Bar<T> {
void flipflop(T x);
}

class BarImpl<T> implements Bar<T> {
Foo<T> foo;

@Inject
BarImpl(Foo<T> foo) { this.foo = foo; }

public void flipflop(T x) { foo.flip(x);
System.out.println("flop: " + x); }
}

interface BarFactory {
<T> Bar<T> create(Foo<T> f);
}

class Module extends AbstractModule {
public void configure() {
bind(BarFactory.class)
.toProvider(
FactoryProvider.newFactory( BarFactory.class,
BarImpl.class )
);
}
}

public class GenericInject {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new Module());

Foo<Integer> foo = new Foo<Integer>();
Bar<Integer> bar =
injector.getInstance(BarFactory.class).create(foo);
bar.flipflop(0);
}
}

When I run the code, I get the following errors from Guice:

1) No implementation for BarFactory was bound.
at Module.configure(GenericInject.java:38)

2) Bar<T> cannot be used as a key; It is not fully specified.

I guess the problem is that the BarFactory.create() method doesn't
match the pattern expected by FactoryProvider, because of the type
quantifier <T>. But there isn't a real problem here: BarImpl.class
(with no type literal) is exactly what we need to create a Bar<T>
given a Foo<T>. Is there a way to configure Guice to generate a
BarFactory instance for me, or do I just need to write the BarFactory
instance by hand?

Sam Berlin

unread,
Oct 4, 2010, 8:54:03 AM10/4/10
to google...@googlegroups.com
See issue 218.  An assisted inject factory itself can be genericized, but its methods cannot introduce their own generic types right now.  So assuming you have a limited number of types T, you can workaround this by changing BarFactory to BarFactory<T> and registering a BarFactory for each T.

 sam
 


--
You received this message because you are subscribed to the Google Groups "google-guice" group.
To post to this group, send email to google...@googlegroups.com.
To unsubscribe from this group, send email to google-guice...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-guice?hl=en.


Chris Conway

unread,
Oct 14, 2010, 6:40:23 PM10/14/10
to google-guice
Sam,

Thanks for your response. It arrived when I was on vacation, so I
apologize for this late reply.

The approach I've taken is to just write out the Factory boilerplate:

class BarFactoryImpl implements BarFactory {
public <T> Bar<T> create(Foo<T> f) {
return new BarImpl<T>(f);
}
}

which then works with the simple binding

bind(BarFactory.class).to(BarFactoryImpl.class);

Regards,
Chris

On Oct 4, 8:54 am, Sam Berlin <sber...@gmail.com> wrote:
> See issue 218 <http://code.google.com/p/google-guice/issues/detail?id=218>.
> > google-guice...@googlegroups.com<google-guice%2Bunsubscribe@google groups.com>
> > .
Reply all
Reply to author
Forward
0 new messages