简体   繁体   English

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

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

I'm currently writing a DSL for a library and I'd like to supply type metadata using reified type parameters like this: 我正在为一个库编写一个DSL,我想使用这样的具体类型参数提供类型元数据:

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

My problem is that i can only use the reified keyword in inline functions and in an inline function I can't use instance fields like this: 我的问题是,我只能用reified关键字inline函数和一个inline函数,我不能用这样的实例字段:

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

because I get an error: 因为我收到一个错误:

Public-API inline function cannot access non-public-API 'private final val consumers... Public-API内联函数无法访问非公共API的私有最终val消费者...

It seems so far that I can't use reified type parameters where they would be most useful. 到目前为止,我似乎无法使用最有用的reified类型参数。 Is there a workaround for this? 这有解决方法吗?

Public inline functions cannot use private declarations directly, because, when inlined at the call sites outside the class, the usages will have incorrect access level (on JVM, a private member of a class cannot be accessed from outside). 公共inline函数不能直接使用private声明,因为当在类外部的调用站点内联时,用法将具有不正确的访问级别(在JVM上,无法从外部访问类的private成员)。

What you can do is use the internal visibility in Kotlin: on JVM, the members with this visibility modifier will be compiled into public members with their names mangled (therefore still visible but not easy-to-call from Java), and the Kotlin compiler will at least control the usages from the Kotlin code. 您可以做的是使用Kotlin中internal可见性 :在JVM上,具有此可见性修饰符的成员将被编译为公共成员,其名称被破坏(因此仍然可见但不容易从Java调用)和Kotlin编译器至少会控制Kotlin代码的用法。

There are a few ways to access an internal member from within a public inline fun , see this question: (link) 有一些方法可以从public inline fun访问internal成员,请参阅此问题:( 链接)

In your particular case, I would prefer doing it with @PublishedApi : 在您的特定情况下,我更喜欢使用@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
}

Or, if you don't mind exposing consumers with @PublishedApi , then you can do it as follows: 或者,如果您不介意使用@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
}

If all that you need the reified type parameter for is to reflect its java class, then you can manage with a non-inline overload with additional Class<T> parameter. 如果您需要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)
}

This way you haven't expose consumers property effectively published. 这样您就没有公开consumers有效发布的财产。 The bonus point is that you can call that non-inline overload also from Java. 奖励点是您也可以从Java调用非内联重载。

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

相关问题 如何使用 Java 中的具体泛型调用 Kotlin 方法? - How can I call Kotlin methods with reified generics from Java? Kotlin:经过修饰的类型参数使Gson失败 - Kotlin: Reified type parameter makes Gson fail 当该实例可能具有不同的数据类型时,如何返回该实例的正确数据类型? - How can I return the right data type of a instance when this instance might have different data type? Kotlin将类型函数作为函数扩展来实现 - 可以从Java调用吗? - Kotlin reified type function as function extension - Callable from Java? 如何以类型安全的方式在查询中存储数据? - How can I store data in a lookup in a type safe way? 什么是Reified Generics?他们如何解决类型擦除问题以及为什么不能在没有重大变化的情况下添加它们? - What are Reified Generics? How do they solve Type Erasure problems and why can't they be added without major changes? 如何从Kotlin数据类创建对象的Java实例,但不包括所有字段? - How to create a Java instance of the object from Kotlin data class but don't include all fields? 如何确定何时将Kotlin类型映射到Java类型? - How can I identify when a Kotlin type will be mapped to a Java type? 我可以将 View 对象存储在实例字段中吗? - May I store View objects in instance fields? 如何在Kotlin中检查数组类型(非泛型类型) - How can I check for array type (not generic type) in Kotlin
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM