Using Guice in Scala, I'm trying to reproduce the following Java code.
Foo interface and class declaration:
public interface Foo[T] {}
public class FooImpl[T] implements Foo[T] {}
Guice binding code:
bind(Foo.class).to(FooImpl.class);
And one use example would be;
@Inject
public class Bar(Foo<String> foo) {}
In scala, my first bet was:
bind(classOf[Foo]).to(classOf[FooImpl])
But it's complaining about 'Type Foo takes type parameter'
How do I achieve this in scala?
Thank you
Your question has an error and thus it allows you for a wrong answer.
Let's first fix your concept idea. Having trait
trait Foo[T] { def hello: T }
works just fine. But then, the specific classes extending this trait will be, f.e.:
class FooImpl1 extends Foo[Int] { override def hello: Int = 42 }
class FooImpl2 extends Foo[String]{ override def hello: String = "test" }
And they could NOT be:
class FooImpl[Int] extends Foo[Int] { override def hello: Int = 42 }
class FooImpl[String] extends Foo[String]{ override def hello: String = "test" }
Because then, the Int
or String
is just the NAME for a generic parameter. It could be as well A
and B
, but you have just confused yourself.
Having this sorted out, you know know that you have FooImpl1
and FooImpl2
.
They need different names because you can not have two classes named the same in the same scope!
And it is just fine. Because when you :
bind(classOf[X]).to(classOf[Y])
You are telling that whenever your class will call methods of the Interface
or Trait
X
you want to provide the implementation of class Y
.
You have to provide a class that you can instantiate! You could not instantiate a class with a generic parameter.
And, to finish, your proper binding would look like this:
bind(new TypeLiteral[Foo[Int]](){}).to(classOf[FooImpl1])
bind(new TypeLiteral[Foo[String]](){}).to(classOf[FooImpl2])