我可以覆盖 returns 单位类型 Java 的 kotlin 方法吗
Can I override kotlin method which returns Unit type in Java
主要问题:如何在java returns 单位类型中覆盖 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摘要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
引用:
I don't think this is possible now because of
compatibility with older binaries. We'll see what we can do, thank you
for the report.
An ugly workaround would be to use the nullable type Unit?
:
interface TestA<out T> {
fun foo(): T
}
abstract class TestB : TestA<Unit?> {
override fun foo(): Unit? {
// ...
return Unit
}
}
With this, you won't be required to override foo
in a Java subclass.
If you want to override it though, the signature in the Java subclass
should be public Unit foo()
.
如果您不控制图书馆,我不确定您能做些什么。
- 如果您控制 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}")
}
}
或者在您的 Java 代码中使用 Any
而不是 Unit
和 return 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}")
}
}
如果不能,我认为最好在 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
尝试用不同的 return 类型覆盖 Function1.invoke
,如 jls-8.4.8.3 中所述,
If a method declaration d1 with return type R1 overrides or hides the
declaration of another method d2 with return type R2, then d1 must be
return-type-substitutable (§8.4.5) for d2, or a compile-time error
occurs.
主要问题:如何在java returns 单位类型中覆盖 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摘要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
引用:
I don't think this is possible now because of compatibility with older binaries. We'll see what we can do, thank you for the report.
An ugly workaround would be to use the nullable type
Unit?
:interface TestA<out T> { fun foo(): T } abstract class TestB : TestA<Unit?> { override fun foo(): Unit? { // ... return Unit } }
With this, you won't be required to override
foo
in a Java subclass. If you want to override it though, the signature in the Java subclass should bepublic Unit foo()
.
如果您不控制图书馆,我不确定您能做些什么。
- 如果您控制 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}") } }
或者在您的 Java 代码中使用
Any
而不是Unit
和 returnnull
: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}") } }
如果不能,我认为最好在 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
尝试用不同的 return 类型覆盖 Function1.invoke
,如 jls-8.4.8.3 中所述,
If a method declaration d1 with return type R1 overrides or hides the declaration of another method d2 with return type R2, then d1 must be return-type-substitutable (§8.4.5) for d2, or a compile-time error occurs.