繁体   English   中英

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

[英]How can I store reified type data in instance fields in Kotlin?

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

    val config = Config.create()
            .consumerFor<MyType>{
              // consume
            }

我的问题是,我只能用reified关键字inline函数和一个inline函数,我不能用这样的实例字段:

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

因为我收到一个错误:

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

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

公共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
}

如果您需要reified类型参数的所有内容都是为了反映其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调用非内联重载。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM