如何在Kotlin的实例字段中存储已知类型的数据?

Ada*_*old 6 java reification kotlin

我正在为一个库编写一个DSL,我想使用这样的具体类型参数提供类型元数据:

    val config = Config.create()
            .consumerFor<MyType>{
              // consume
            }
Run Code Online (Sandbox Code Playgroud)

我的问题是我只能reifiedinline函数和函数中使用关键字inline我不能使用像这样的实例字段:

    inline fun <reified T> consumerFor(consumer: (T) -> Unit) {
        consumers.put(T::class.java, consumer)
        return this
    }
Run Code Online (Sandbox Code Playgroud)

因为我收到一个错误:

Public-API内联函数无法访问非公共API的私有最终val消费者...

到目前为止,我似乎无法使用最有用的reified类型参数.这有解决方法吗?

hot*_*key 7

公共inline函数不能private直接使用声明,因为,当在类外部的调用站点内联时,用法将具有不正确的访问级别(在JVM上,private无法从外部访问类的成员).

您可以做的是使用Kotlin中internal可见性:在JVM上,具有此可见性修饰符的成员将被编译为公共成员,其名称被破坏(因此仍然可见但不容易从Java调用),并且Kotlin编译器将至少控制Kotlin代码的用法.

有几种方法可以internal从a中访问成员public inline fun,请参阅此问题:( 链接)

在您的特定情况下,我更愿意这样做@PublishedApi:

private val consumers = mutableMapOf<Class<*>, Any>()

@PublishedApi
internal fun <T> putConsumer(clazz: Class<out T>, consumer: (T) -> Unit) {
    consumers.put(clazz, consumer)
}

inline fun <reified T> consumerFor(noinline consumer: (T) -> Unit): C {
    putConsumer(T::class.java, consumer)
    return this
}
Run Code Online (Sandbox Code Playgroud)

或者,如果你不介意暴露consumers@PublishedApi,那么你可以如下做到这一点:

@PublishedApi
internal val consumers = mutableMapOf<Class<*>, Any>()

inline fun <reified T> consumerFor(noinline consumer: (T) -> Unit): C {
    consumers.put(T::class.java, consumer)
    return this
}
Run Code Online (Sandbox Code Playgroud)