来自通用接口的扩展函数

Extension function from a generic interface

考虑以下界面

interface EntityConverter<in A, out B> {
    fun A.convert(): B

    fun List<A>.convert(): List<B> = this.map { it.convert() }
}

我想在 spring 引导应用程序中使用它,在该应用程序中注入特定的实现,以便扩展函数在该类型上可用。

但是这不起作用。编译器不解析扩展函数。

我不确定您是否可以将扩展函数作为接口的一部分提及,因为它就像静态函数。

我建议将“通用”函数放在带有 A 类型参数的接口中。然后把列表的扩展方法放在附近。

interface EntityConverter<in A, out B> {
    fun convert(a: A): B    
}

fun <A, B> EntityConverter<A, B>.convert(list: List<A>): List<B> = list.map { convert(it) }

更新

我不知道在 Kotlin 中继承扩展方法的可能性。还有关于它的压倒一切。所以我的答案可能只是使用扩展方法的替代方法。

请注意,您定义的扩展函数是 也是 EntityConverter 类型的成员函数。您应该查看 this part of the doc 以了解有关其工作原理的信息。

基本上,为了使用它们,您需要在范围内有 2 个实例:

  • 调度接收器(EntityConverter<A, B>的一个实例)
  • extension 接收器(AList<A> 的实例,其中 A 匹配 EntityConverter 在范围内)

您可以使用 with()EntityConverter 引入范围内,这样您就可以使用 . 语法在其他实例上使用 convert

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]

现在您必须确定这种使用模式是否对您的用例最有意义。如果您更喜欢没有扩展的更多“经典”调用(converter.convert(a) 返回 B),您可以将函数声明为采用参数而不是接收器的常规方法。

奖励:功能界面

附带说明一下,如果您在 EntityConverter 界面前添加 fun 关键字,您可以像这样轻松地创建它的实例:

val converter = EntityConverter<Int, String> { "#$this" }

这是因为您的转换器接口只有一个抽象方法,因此很容易用一个 lambda 表达式实现。请参阅有关 functional interfaces.

的文档