用Java扩展Kotlin类要求我重新实现已经实现的方法

Erl*_*lik 7 java kotlin

证明问题的最简单的代码是这样的:

Kotlin的主要界面:

interface Base <T : Any> {
  fun go(field: T)
}
Run Code Online (Sandbox Code Playgroud)

实现它的抽象类及其方法:

abstract class Impl : Base<Int> {
  override fun go(field: Int) {}
}
Run Code Online (Sandbox Code Playgroud)

Java类:

public class JavaImpl extends Impl {
}
Run Code Online (Sandbox Code Playgroud)

它应该可以,但是不能。错误是

类'JavaImpl'必须声明为抽象,或者必须在'Base'中实现抽象方法'go(T)'

如果JavaImpl类位于Kotlin中,它将起作用。同样,如果将T强制转换为StringInteger或任何对象,它也将起作用。但不是Int。

除了使用Integer并抑制Kotlin子类中的数百个警告外,还有什么聪明的解决方案?

更新:创建了问题

Rol*_*and 3

查看字节码我们可以看到,该类Impl基本上生成了以下函数:

public go(I)V
Run Code Online (Sandbox Code Playgroud)

其中参数是原始整数。还会生成一个合成桥接函数 ( go(Object)),但它也会在 Java 端针对此类通用函数生成。

然而,在 Java 方面,仅仅拥有类似的东西是不够的public void go(int field)。现在我们需要那个go(Integer field)- 函数,但它不存在。对我来说,这听起来就像一个互操作问题,可能应该报告并再次链接回此处。实际上已经花了一些时间进行调查,似乎已经存在一些问题:KT-17159KT-30419,而且KT-5128似乎也与这个问题有关。kotlin 编译器知道如何处理这个问题,并且不需要在类文件中提供任何有关它的进一步信息(即实现的 Kotlin 类知道,它不需要实现类似的东西fun go(field : Int?))。对于 Java 端来说,这样的对应物不存在。我想知道这是否可以通过编译器/字节码很好地解决,或者这是否仍然是一个特定的互操作问题。

处理该问题的一些解决方法(如果这是故意的而不是真正的问题):

  1. 添加一个附加函数如下Impl

    fun go(field : Int?) = go(field ?: error("Actually the given field should never be null"))
    // or simply:
    fun go(field : Int?) = go(field!!)
    
    Run Code Online (Sandbox Code Playgroud)

    这样您就不需要实施它。但是,您还会向 Kotlin 端公开该可为 null 的函数,而您可能不希望这样做。

  2. 出于该特定目的,以相反的方式执行似乎更方便:在 Java 中声明类和接口并在 Kotlin 端使用它。这样你仍然可以声明类似的东西

    abstract class KotlinClass : JavaInterface<Int> {
      override fun go(field : Int) { // an IDE might suggest you to use Int? here...
        // ...
      }
    }
    
    Run Code Online (Sandbox Code Playgroud)