【问题标题】:Can I override kotlin method which returns Unit type in Java我可以覆盖在 Java 中返回 Unit 类型的 kotlin 方法吗
【发布时间】:2021-03-02 02:21:16
【问题描述】:

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

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

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

我在java中尝试了public Unit invoke() { return Unit.INSTANCE; },但出现编译错误。

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 抽象类(在我的项目中)

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

【问题讨论】:

标签: java kotlin overriding


【解决方案1】:

看起来像一个 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()

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

【讨论】:

  • 哦...这对我来说是个坏消息。我无法控制图书馆。我会找到另一种方式。谢谢你的回答!
【解决方案2】:
  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) -&gt; 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 的 return-type-substitutable (§8.4.5),或编译时错误 发生。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多