来自通用接口的扩展函数
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 接收器(
A
或 List<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.
的文档
考虑以下界面
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 接收器(
A
或List<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.
的文档