繁体   English   中英

我可以覆盖返回 Java 中的单位类型的 kotlin 方法吗

[英]Can I override kotlin method which returns Unit type in Java

主要问题:如何在返回 Unit 类型的 java 中覆盖 kotlin 方法?

我正在尝试在 java 中使用 kotlin 库,并且有一个名为override fun invoke(): Unit我必须实现的方法。

但是,java 编译器一直告诉我return type void is not compatible with Unit

我试过public Unit invoke() { return Unit.INSTANCE; } public Unit invoke() { return Unit.INSTANCE; }在 java 但发生编译错误。

invoke()' in 'myproject' clashes with 'invoke()' in 'library'; 
attempting to use incompatible return type

kotlin 接口(在库中)

interface MessageHandler<M : Message> : (Message) -> Unit {

  override fun invoke(message: Message): Unit =
    if (messageType.isAssignableFrom(message.javaClass)) {
      println("invoked ${message.javaClass.simpleName}")
    } else {
      throw IllegalArgumentException("Unsupported message type ${message.javaClass.simpleName}")
    }

}

java 抽象 class (在我的项目中)

public abstract class AbstractMessageHandler<T extends Message> implements MessageHandler<T> {

    @Override
    public void invoke(@NotNull Message message) {
        //this is where the compile error occurs.
    }
}

错误信息

(Message) in AbstractMessageHandler cannot implement invoke(P1) in Function1
    public void invoke(@NotNull Message message) {
                ^
  return type void is not compatible with Unit
  where P1,R are type-variables:
    P1 extends Object declared in interface Function1
    R extends Object declared in interface Function1

看起来像一个 4 年前未解决的错误: https://youtrack.jetbrains.com/issue/KT-15964

引:

由于与旧二进制文件的兼容性,我认为现在不可能。 我们会看看我们能做些什么,谢谢你的报告。

一个丑陋的解决方法是使用可空类型Unit?

 interface TestA<out T> { fun foo(): T } abstract class TestB: TestA<Unit?> { override fun foo(): Unit? { //... return Unit } }

有了这个,您将不需要在 Java 子类中覆盖foo 如果你想覆盖它,Java 子类中的签名应该是public Unit foo()

如果你不控制图书馆,我不确定你能做什么。

  1. 如果您控制 Kotlin 库,您可以:
  • java.util.function.Consumer继承:

     interface MessageHandler<M: Message>: Consumer<Message> { override fun accept(message: Message): Unit = if (messageType.isAssignableFrom(message.javaClass)) { println("invoked ${message.javaClass.simpleName}") } else { throw IllegalArgumentException("Unsupported message type ${message.javaClass.simpleName}") } }
  • 或者使用Any代替Unit并在 Java 代码中返回null

     interface MessageHandler<M: Message>: (Message) -> Any { override fun accept(message: Message): Any = if (messageType.isAssignableFrom(message.javaClass)) { println("invoked ${message.javaClass.simpleName}") } else { throw IllegalArgumentException("Unsupported message type ${message.javaClass.simpleName}") } }
  1. 如果不能,我认为最好,如果可能的话,在 Kotlin 中编写AbstractMessageHandler及其所有子类:

     abstract class AbstractMessageHandler: MessageHandler<Message> { override fun invoke(message: Message) { //... } }
  • 但是,如果您不调用默认MessageHandler.invoke并且您的代码与MessageHandler类型无关,您可以简单地从java.util.function.Consumer继承:

     public class AbstractMessageHandler implements Consumer<Message> { @Override public void accept(Message message) { //... } }

只是在错误之前提一下:

(Message) in AbstractMessageHandler cannot implement invoke(P1) in Function1
...

您应该会看到如下内容:

'invoke(Message)' in '...MessageHandler' clashes with 'invoke(P1)' in 
'kotlin.jvm.functions.Function1'; attempting to use incompatible return type

因为 Java 编译器看到两个接口,一个来自(Message) -> Unit

public interface kotlin.jvm.functions.Function1 {
   Object invoke(Messsage var1);
}

另一个来自MessageHandler

public interface MessageHandler extends Function1 {
   void invoke(@NotNull Message var1);
}

// (Some details were ommitted for simplicity)

这在 Java 中是不可能的,因为MessageHandler.invoke尝试使用不同的返回类型覆盖Function1.invoke ,如jls-8.4.8.3中所述,

如果具有返回类型 R1 的方法声明 d1 覆盖或隐藏具有返回类型 R2 的另一个方法 d2 的声明,则 d1 必须是 d2 的返回类型可替换( 第 8.4.5 节),否则会发生编译时错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM