考虑以下接口
interface EntityConverter<in A, out B> {
fun A.convert(): B
fun List<A>.convert(): List<B> = this.map { it.convert() }
}
我想在注入特定实现的 Spring Boot 应用程序中使用它,以便扩展功能可用于该类型。
但是,这不起作用。编译器不解析扩展函数。
考虑以下接口
interface EntityConverter<in A, out B> {
fun A.convert(): B
fun List<A>.convert(): List<B> = this.map { it.convert() }
}
我想在注入特定实现的 Spring Boot 应用程序中使用它,以便扩展功能可用于该类型。
但是,这不起作用。编译器不解析扩展函数。
请注意,您定义的扩展函数也是EntityConverter
该类型的成员函数。您应该查看文档的这一部分以了解有关其工作原理的信息。
本质上,为了使用它们,您需要 2 个范围内的实例:
EntityConverter<A, B>
)A
接收器( or的一个实例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)
返回 a B
),您可以将您的函数声明为采用参数而不是接收器的常规方法。
作为旁注,如果您fun
在界面前面添加关键字EntityConverter
,您可以像这样非常轻松地创建它的实例:
val converter = EntityConverter<Int, String> { "#$this" }
这是因为您的转换器接口只有一个抽象方法,因此很容易使用单个 lambda 实现。请参阅有关功能接口的文档。
我不确定您是否可以将扩展函数作为接口的一部分提及,因为它就像静态函数。
我建议将“通用”函数放在带有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 中继承扩展方法的可能性。关于它的压倒一切。所以我的答案可能只是使用扩展方法的替代方法。