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

时间:2017-03-11 22:48:34

标签: java kotlin reification

我目前正在为图书馆编写DSL,我想使用这样的具体类型参数提供类型元数据:

100%

我的问题是我只能在 val config = Config.create() .consumerFor<MyType>{ // consume } 函数中使用reified关键字,而在inline函数中我无法使用像这样的实例字段:

inline

因为我收到错误:

  

Public-API内联函数无法访问非公共API的私有最终用户...

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

2 个答案:

答案 0 :(得分:7)

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

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

有几种方法可以在internal内访问public inline fun成员,请参阅此问题:(link)

在您的特定情况下,我更愿意使用@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
}

或者,如果您不介意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
}

答案 1 :(得分:1)

如果您需要的是reified type参数,那么您可以使用其他Class<T>参数来管理非内联重载。

inline fun <reified T> consumerFor(noinline consumer: (T) -> Unit) =
    consumerFor(T::class.java, consumer)

fun <T> consumerFor(key: Class<T>, consumer: (T) -> Unit) = apply {
    consumers.put(key, consumer)
}

这样您就没有公开有效发布的consumers属性。奖励点是您也可以从Java调用非内联重载。