Consider the following interface
interface EntityConverter<in A, out B> {
fun A.convert(): B
fun List<A>.convert(): List<B> = this.map { it.convert() }
}
I want to use it in a spring boot application where specific implementations get injected so that the extension function becomes usable on the type.
However this doesn't work. The compiler does not resolve the extension function.
Note that you're defining extension functions that are also member functions of the EntityConverter
type. You should take a look at this part of the doc for information about how this works.
Essentially, in order to use them, you need 2 instances in scope:
EntityConverter<A, B>
)A
or List<A>
, where A
matches the first type parameter of the EntityConverter
in scope)You can use with() to bring the EntityConverter
in scope so you can use convert
on your other instances using the usual .
syntax:
val converter = object : EntityConverter<Int, String> {
override fun Int.convert() = "#$this"
}
val list = listOf(1, 2, 3)
val convertedList = with(converter) {
list.convert()
}
println(convertedList) // prints [#1, #2, #3]
Now you have to decide whether this kind of usage pattern is what makes most sense for your use case. If you'd prefer more "classic" calls without extensions (converter.convert(a)
returning a B
), you can declare your functions as regular methods taking an argument instead of a receiver.
As a side note, if you add the fun
keyword in front of your EntityConverter
interface, you can create instances of it very easily like this:
val converter = EntityConverter<Int, String> { "#$this" }
This is because your converter interface only has a single abstract method, making it easy to implement with a single lambda. See the docs about functional interfaces.