3

考虑以下接口

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

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

我想在注入特定实现的 Spring Boot 应用程序中使用它,以便扩展功能可用于该类型。

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

4

2 回答 2

2

请注意,您定义的扩展函数也是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 实现。请参阅有关功能接口的文档。

于 2021-09-02T08:45:49.990 回答
1

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

我建议将“通用”函数放在带有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 中继承扩展方法的可能性。关于它的压倒一切。所以我的答案可能只是使用扩展方法的替代方法。

于 2021-09-02T07:56:36.970 回答