如何在 Kotlin 的实例字段中存储具体化的类型数据?
How can I store reified type data in instance fields in Kotlin?
我目前正在为一个库编写 DSL,我想使用像这样的具体化类型参数来提供类型元数据:
val config = Config.create()
.consumerFor<MyType>{
// consume
}
我的问题是我只能在 inline
函数中使用 reified
关键字,而在 inline
函数中我不能使用这样的实例字段:
inline fun <reified T> consumerFor(consumer: (T) -> Unit) {
consumers.put(T::class.java, consumer)
return this
}
因为我得到一个错误:
Public-API inline function cannot access non-public-API 'private final val consumers...
到目前为止,我似乎无法在最有用的地方使用具体化的类型参数。有解决办法吗?
Public inline
函数不能直接使用 private
声明,因为当在 class 之外的调用点内联时,用法将具有不正确的访问级别(在 JVM 上,无法从外部访问 class 的 private
成员。
你可以做的是在 Kotlin 中使用 the internal
visibility:在 JVM 上,具有此可见性修饰符的成员将被编译为 public 名称被破坏的成员(因此仍然可见但不容易-从 Java 调用),Kotlin 编译器至少会控制 Kotlin 代码中的用法。
有几种方法可以从 public inline fun
中访问 internal
成员,请参阅此问题:
在您的特定情况下,我更愿意使用 @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
}
如果您只需要具体化类型参数来反映其 java class,那么您可以使用带有附加 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.
调用非内联重载
我目前正在为一个库编写 DSL,我想使用像这样的具体化类型参数来提供类型元数据:
val config = Config.create()
.consumerFor<MyType>{
// consume
}
我的问题是我只能在 inline
函数中使用 reified
关键字,而在 inline
函数中我不能使用这样的实例字段:
inline fun <reified T> consumerFor(consumer: (T) -> Unit) {
consumers.put(T::class.java, consumer)
return this
}
因为我得到一个错误:
Public-API inline function cannot access non-public-API 'private final val consumers...
到目前为止,我似乎无法在最有用的地方使用具体化的类型参数。有解决办法吗?
Public inline
函数不能直接使用 private
声明,因为当在 class 之外的调用点内联时,用法将具有不正确的访问级别(在 JVM 上,无法从外部访问 class 的 private
成员。
你可以做的是在 Kotlin 中使用 the internal
visibility:在 JVM 上,具有此可见性修饰符的成员将被编译为 public 名称被破坏的成员(因此仍然可见但不容易-从 Java 调用),Kotlin 编译器至少会控制 Kotlin 代码中的用法。
有几种方法可以从 public inline fun
中访问 internal
成员,请参阅此问题:
在您的特定情况下,我更愿意使用 @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
}
如果您只需要具体化类型参数来反映其 java class,那么您可以使用带有附加 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.