如何将实例类型数据存储在Kotlin的实例字段中?
我目前正在写一个库的DSL,我想提供使用像这样的具体类型参数的类型元数据:
val config = Config.create() .consumerFor<MyType>{ // consume }
我的问题是,我只能reified
inline
函数中使用reified
关键字,而reified
inline
函数中我不能使用像这样的实例字段:
inline fun <reified T> consumerFor(consumer: (T) -> Unit) { consumers.put(T::class.java, consumer) return this }
因为我得到一个错误:
公共API内联函数不能访问非公共API的私有最终val消费者…
看来到目前为止,我不能在最有用的地方使用实体类型参数。 有没有解决方法?
公共inline
函数不能直接使用private
声明,因为当在类外的调用站点内联时,用法将具有不正确的访问级别(在JVM上,一个类的private
成员不能从外部访问)。
您可以使用Kotlin中的internal
可见性 :在JVM上,具有此可见性修饰符的成员将被编译为公共成员,并且其名称被破坏(因此仍然可见但不易于从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 }
或者,如果你不介意使用@PublishedApi
公开consumers
,那么你可以这样做:
@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<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调用非内联重载。