Reputation: 16600
The following code works fine and the call to the foo.get()
extension function returns the correct type BarImpl.
open class Bar
class BarImpl: Bar()
class Foo<T : Bar>
inline fun <reified T : Bar> Foo<T>.get(): T {
return SomeMap(this).get(T::class)
}
class Activity {
lateinit var foo: Foo<BarImpl>
val barImpl = foo.get()
}
But when I try to move Foo<T>.get()
into the class the type inference fails
class Foo<T : Bar> {
inline fun <reified T : Bar> get(): T {
return SomeMap(this).get(T::class)
}
}
class Activity {
lateinit var foo: Foo<BarImpl>
val barImpl = foo.get()
}
error: type inference failed: Not enough information to infer parameter T in inline fun get(): T Please specify it explicitly.
val vm = foo.get() ^
How can I move the function into the class?
Upvotes: 1
Views: 97
Reputation: 2502
The extension function returns the result of the Foo
type parameter. So the result type can be inferred from the receiver type.
And the member function result type has nothing in common with Foo
type parameter except the name, which means nothing for a compiler. You can see that T
in method and T
in class are different types by writing and compiling the following code:
Foo<BarImpl>().get<BarImpl2>()
If you want to make get
to be a member function which returns the result of Foo
type parameter, you should remove type parameter from function and inject class instance via the constructor:
class Foo<T : Bar>(private val clazz: KClass<T>) {
fun get(): T {
return SomeMap(this).get(clazz)
}
companion object {
inline operator fun <reified T : Bar> invoke() = Foo(T::class)
}
}
Upvotes: 4