Kotlin 覆盖歧义

Kotlin override ambiguity

我必须为我的 Quarkus 应用程序创建自定义日志记录提供程序,以将日志条目转换为 Google 云 JSON 格式。
为此,提供者 class(用 Kotlin 编写)必须扩展名为 ExtFormatter 的抽象 class(来自第 3 方库,用 Java 编写),它有这两种方法:

package org.jboss.logmanager;
[...]

public abstract class ExtFormatter extends Formatter {
   public final String format(final LogRecord record) {
      return format(ExtLogRecord.wrap(record));
   }

   [...]
}

public abstract String format(ExtLogRecord record);

ExtLogRecordLogRecord 的子 class,因此方法签名非常相似。
我的日志提供程序实现了这样的抽象方法:

import io.quarkiverse.loggingjson.JsonProvider
import org.jboss.logmanager.ExtFormatter
import org.jboss.logmanager.ExtLogRecord
[...]

class JsonLoggingProvider : JsonProvider, ExtFormatter() {
   override fun format(extLogRecord: ExtLogRecord?) = null
}

当我 运行 应用程序时(不是在编译时),我得到这个错误:

java.lang.VerifyError: class com.mycompany.logging.JsonLoggingProvider_Subclass overrides final method org.jboss.logmanager.ExtFormatter.format(Ljava/util/logging/LogRecord;)Ljava/lang/String;
        at java.base/java.lang.ClassLoader.defineClass1(Native Method)
        at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1017)
        at io.quarkus.bootstrap.classloading.QuarkusClassLoader.loadClass(QuarkusClassLoader.java:437)
        at io.quarkus.bootstrap.classloading.QuarkusClassLoader.loadClass(QuarkusClassLoader.java:397)
        at com.mycompany.logging.JsonLoggingProvider_Bean.create(JsonLoggingProvider_Bean.zig:368)
        at com.mycompany.logging.JsonLoggingProvider_Bean.create(JsonLoggingProvider_Bean.zig:394)
        at io.quarkus.arc.impl.AbstractSharedContext.createInstanceHandle(AbstractSharedContext.java:96)
        at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:29)
        at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:26)
        at io.quarkus.arc.impl.LazyValue.get(LazyValue.java:26)
        at io.quarkus.arc.impl.ComputingCache.computeIfAbsent(ComputingCache.java:69)
        at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:26)
        at com.mycompany.logging.JsonLoggingProvider_Bean.get(JsonLoggingProvider_Bean.zig:426)
        at com.mycompany.logging.JsonLoggingProvider_Bean.get(JsonLoggingProvider_Bean.zig:442)
        at io.quarkus.arc.impl.InstanceImpl.getBeanInstance(InstanceImpl.java:210)
        at io.quarkus.arc.impl.InstanceImpl$InstanceIterator.next(InstanceImpl.java:246)
        at java.base/java.lang.Iterable.forEach(Iterable.java:74)
        at io.quarkiverse.loggingjson.LoggingJsonRecorder.initializeJsonLogging(LoggingJsonRecorder.java:62)
        at io.quarkus.deployment.steps.LoggingJsonProcessor$setUpFormatter-614569086.deploy_0(LoggingJsonProcessor$setUpFormatter-614569086.zig:88)
        at io.quarkus.deployment.steps.LoggingJsonProcessor$setUpFormatter-614569086.deploy(LoggingJsonProcessor$setUpFormatter-614569086.zig:40)
        at io.quarkus.runner.ApplicationImpl.doStart(ApplicationImpl.zig:666)
        at io.quarkus.runtime.Application.start(Application.java:101)
        at io.quarkus.runtime.ApplicationLifecycleManager.run(ApplicationLifecycleManager.java:101)
        at io.quarkus.runtime.Quarkus.run(Quarkus.java:66)
        at io.quarkus.runtime.Quarkus.run(Quarkus.java:42)
        at io.quarkus.runtime.Quarkus.run(Quarkus.java:119)
        at io.quarkus.runner.GeneratedMain.main(GeneratedMain.zig:29)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at io.quarkus.runner.bootstrap.StartupActionImpl.run(StartupActionImpl.java:98)
        at java.base/java.lang.Thread.run(Thread.java:829)

由于某种原因,错误的方法(或两种方法?)似乎被覆盖了。
我怀疑它的发生是因为这些方法或多或少具有相同的签名。 有没有办法让 Kotlin 覆盖更精确以避免这个问题?

与我最初的假设相反,问题显然不是由 Kotlin 引起的,而是由 Quarkus 引起的。依赖注入似乎被非常相似的方法搞糊涂了。由于我无法更改任何方法名称或签名,因为它们来自第三方 Quarkiverse 库,因此我通过不再子类化 ExtFormatter 来解决这个问题,而是实例化它的一个已经存在的子类 JsonFormatter :

import io.quarkiverse.loggingjson.JsonGenerator
import io.quarkiverse.loggingjson.JsonProvider
import org.jboss.logmanager.ExtLogRecord
import org.jboss.logmanager.formatters.JsonFormatter
[...]

class JsonLoggingProvider : JsonProvider {
  private val jsonFormatter = JsonFormatter()
  
  private fun writeMessage(generator: JsonGenerator, event: ExtLogRecord) {
      val message = jsonFormatter.formatMessage(event)
      [...]
  }
}

再次感谢broot帮助我!