【问题标题】:Extension function from a generic interface通用接口的扩展函数
【发布时间】:2021-09-02 07:47:55
【问题描述】:

考虑如下界面

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

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

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

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

【问题讨论】:

    标签: kotlin generics extension-function


    【解决方案1】:

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

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

    • dispatch 接收器(EntityConverter&lt;A, B&gt; 的一个实例)
    • 扩展接收器(AList&lt;A&gt; 的实例,其中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 的文档。

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • 所以您看不到将扩展功能放在A / List&lt;A&gt; 上的方法吗?
      • 这不太正确。扩展绝对可以是成员并且不是静态的,它们可以从封闭类访问状态。这是 Kotlin 中基于上下文编程的主要工具
      • @Joffrey Documentation 说扩展函数“是静态调度的,这意味着它们不是按接收器类型虚拟的”。我不确定实施,但它们的行为就像是静态的。
      • 对不起,如果我不清楚。常规扩展函数确实是静态调度的。然而,成员扩展仅相对于它们的 extension 接收器静态调度,但实际上相对于它们的 dispatch 接收器。所以他们可以被他们的调度接收者覆盖。在Declaring extensions as members 中有解释(请刷新,因为链接看起来很奇怪)
      猜你喜欢
      • 2022-11-04
      • 1970-01-01
      • 2020-06-09
      • 2020-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-08
      • 1970-01-01
      相关资源
      最近更新 更多