【问题标题】:How to force Kotlin to call a particular overloaded method in Java interface?如何强制 Kotlin 在 Java 接口中调用特定的重载方法?
【发布时间】:2021-07-18 17:28:53
【问题描述】:

有一个Java接口

interface MyContract {
  
  <M> void execute(Class<M> argClass, Consumer<M> action);

  <M, R> R execute(Class<M> argClass, Function<M, R> action);
}

默认情况下,从 Kotlin 代码中调用 execute 方法时,编译器总是使用第一个重载方法,即使显式设置了预期类型,也会出现编译错误:

MyContract myContract = createSomehow();
val x: Int = myContract.execute(SomeClass::class.java, { it -> 1})  

Compilation error:
Type mismatch: inferred type is Unit but Int was expected

为了强制编译器使用第二个重载方法,我添加了这个样板:

val fn: (SomeClass) -> Int = { it -> 1 }
val x: Int = myContract.execute(SomeClass::class.java, fn)  

在这种情况下,表达意图调用特定重载方法的正常语法方式是什么?

【问题讨论】:

  • 你可以强制你的第二个参数显式地成为一个函数:val x = myContract.execute(SomeClass::class.java, Function{ it -&gt; 1 }).
  • 你还需要import java.util.function.Function,因为kotlin.Function是默认导入的。

标签: kotlin methods overloading


【解决方案1】:

这个问题不是 java-interop 特有的,如果在 Kotlin 中定义了类似的接口,错误将是相同的。看起来有空间增强重载解决机制。

对于一种解决方法,您可以使用这样一个事实,即重载方法具有不同数量的类型参数,因此您可以显式指定它们:

val x = myContract.execute<SomeClass, Int>(SomeClass::class.java) { it -> 1 }

这仍然很吵,所以我建议声明 Kotlin 特定的 API:

internal inline fun <reified M> MyContract.execute(noinline action: ((M) -> Unit)?) = execute(M::class.java, action)
internal inline fun <reified M, R> MyContract.execute(noinline action: ((M) -> R)?) = execute(M::class.java, action)

现在它可以被调用:

val x = myContract.execute<SomeClass, Int> { it -> 1 }

【讨论】:

  • 看起来很强大:5 个 Kotlin 的超强功能合而为一。谢谢你的回答
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-07
  • 1970-01-01
  • 2020-03-02
  • 1970-01-01
相关资源
最近更新 更多