如何在 Kotlin 中指定递归泛型参数?

vag*_*ran 6 generics log4j kotlin

我只想从使用 Log4j (v2.8.2) 的 Java 移植以下代码:

ConsoleAppender appender = ConsoleAppender.newBuilder().
            withName("ConsoleAppender").build();
Run Code Online (Sandbox Code Playgroud)

问题在于 newBuilder() 方法,该方法在 log4j 中被定义为某种递归泛型:

@PluginBuilderFactory
public static <B extends Builder<B>> B newBuilder() {
    return new Builder<B>().asBuilder();
}
Run Code Online (Sandbox Code Playgroud)

Java 代码会自动推断泛型参数,而 Kotlin 则不然。在 Kotlin 中调用这个方法有什么解决方案吗?

我在 Kotlin 中尝试过的代码:

val appender = ConsoleAppender.newBuilder().withName("ConsoleAppender").build()
Run Code Online (Sandbox Code Playgroud)

它有以下错误:

错误:(90, 48) Kotlin:类型推断失败:没有足够的信息来推断 fun 中的参数 B !> newBuilder(): B!请明确指定。

当代码在粘贴时自动从 Java 转换时,它会设置一些存根newBuilder<B>(),其中 B 未定义,我不知道它应该是什么。

Kon*_*tor 3

Log4J 似乎使用一种构建器模式,在 Kotlin 中要求每个开放的非抽象类都有两个构建器:一个泛型,可以通过子类扩展,另一个非泛型,可以实例化。

由于您可能不想修改 Log4J,我会考虑使用反射:

fun main(args: Array<String>) {
    val builder = ConsoleAppender::class.java.getMethod("newBuilder").invoke(null) as ConsoleAppender.Builder<*>
    val appender = builder.withName("ConsoleAppender").build()
    println(appender.name)
}
Run Code Online (Sandbox Code Playgroud)

请参阅我的回答:discuss.kotlinlang.org

构建器模式中的递归泛型