Scala Dependency injection with generic class

2020-05-02 04:27发布

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

1条回答
时光不老,我们不散
2楼-- · 2020-05-02 04:58

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])
查看更多
登录 后发表回答