Guice Typeliteral for kotlin collection (e.g. kotlin.collections.Iterable) searches for java.lang.Iterable

Viewed 121

Problem

In kotlin, with the following module configuration for guice

fun configureFoo(binder: Binder) {
  binder.bind(object: TypeLiteral<Foo<Iterable<Any>>>() {}).to(MyFoo::class.java)
}

And the example classes

interface Foo<T> {
  // ...
}

class MyFoo : Foo<Iterable<Any>> {
  // ...
}

class User @Inject constructor(foo: Foo<Iterable<Any>>) {
  // ...
}

I get the guice configuration error:

No implementation for Foo<java.lang.Iterable<Any>> was bound. ...

What I've tried

I can fix this by changing Iterable to java.lang.Iterable everywhere... but thats a bad workaround loosing all the benefits of kotlin.collections.Iterable.

Question

Does anyone know this problem and has a better solution?

1 Answers

Simple workaround until a better solution arrives

Right now I'm using a workaround as follows, in case anyone stumbles upon that problem:

I define specialized MultiFoo<Any>s and use them instead of Foo<Iterable<Any>> whenever I want to use an iterable type-parameter for Foo:

fun configureFoo(binder: Binder) {
  // bind an iterable Any for Foo
  binder.bind(object: TypeLiteral<MultiFoo<Any>>() {}).to(MyFoo::class.java)

  // bind a single Any For Foo
  binder.bind(object: TypeLiteral<Foo<Any>>() {}).to(MySingleFoo::class.java)
}
interface Foo<T> {
  // ...
}
interface MultiFoo<T>: Foo<Iterable<T>> {
  // ...
}

class MyFoo : MultiFoo<Any> {
  // ...
}

class MySingleFoo : Foo<Any> {
  // ...
}
class User @Inject constructor(foo: MultiFoo<Any>, bar: Foo<Any>) {
  // ...
}

Although it is not very beautiful to create and use extra classes for injection-binding and constructor-parameters, but at least the injected-classes adhere to the desired interface-contracts... I can use MultiFoo<Any> as a Foo<Iterable<Any>>

Related