【问题标题】:Extend 2 lambda with different signature in Kotlin在 Kotlin 中使用不同的签名扩展 2 lambda
【发布时间】:2019-05-24 11:56:14
【问题描述】:

在 Kotlin 中,我们无法创建实现 2 个具有不同签名的 lambda 的类,如下所示:

class Test<T> : (T) -> Unit, () -> T {
    ...
}

出现以下错误:

'Function' 的类型参数 R 的值不一致:Unit, T

我理解它发生的原因:所有 lambda 都是FunctionN 接口,所有FunctionN 接口都扩展了一些称为Function 的标记接口,它不能被调用。但最后一个也是上面提到的泛型冲突和错误的根本原因。

我的问题可能是 Kotlin 团队:有什么理由为什么所有 FunctionN 扩展 Function 接口?也许一些内部/字节码的东西对我们来说并不明显,但对底层的性能进行了一些棘手的优化。

【问题讨论】:

标签: kotlin


【解决方案1】:

https://github.com/JetBrains/kotlin/blob/master/spec-docs/function-types.md 提供了一些关于Function 使用的有限信息:

  • 在编译器前端引入物理类 Function 和无限数量的虚构(合成)类 Function0Function1、...

  • 提供一种方法来获取任意Function 对象的数量(非常简单)。

  • 在 codegen 中的任何编号函数上破解 is/as Function5(可能在反射中使用 KClass.cast())以检查 Function 及其数量。

(注意:虚构的Function* 类在kotlin 包中,kotlin.jvm.functions.Function* 接口是真实的。)

此方法修复的问题列在“目标”部分:

  • 摆脱 23 个硬连线物理功能类。它们的问题之一是它们应该在反射中有效地复制,这意味着 kotlin-runtime.jar 中有很多物理类。
  • 使扩展函数可分配给普通函数(反之亦然),这样就可以做到listOfStrings.map(String::length)
  • 允许具有超过 23 个参数的函数,理论上是任意数量的参数(实际上在 JVM 上为 255 个)。
  • 同时,允许从 Java 轻松实现 Kotlin 函数:new Function2() { ... } 并仅覆盖 invoke 是最好的。在 Java 8 上启用 SAM 转换也很棒。

【讨论】:

    【解决方案2】:

    我认为您可以简单地手动重载调用方法以获取 lamdbas 的行为:

    class Test<T> {
        operator fun invoke(p1: T) {
        }
    
        operator fun invoke(): T {
            return ...
        }
    }
    

    要联系 Kotlin 团队,您可以在论坛 (https://discuss.kotlinlang.org) 上找到他们,或提交问题 (https://youtrack.jetbrains.com/issues/KT)。

    【讨论】:

      猜你喜欢
      • 2020-06-15
      • 1970-01-01
      • 2020-09-10
      • 2021-07-05
      • 2010-09-24
      • 1970-01-01
      • 2015-09-01
      • 1970-01-01
      • 2011-02-11
      相关资源
      最近更新 更多