具体化类型参数和内部结构

dan*_*iol 4 generics inline kotlin

我有一个泛型函数,需要实例化其泛型参数的对象并将其传递给某个接口的实例。
据我所知,实例化通用对象的唯一方法是使函数内联并具体化该类型参数。但我不想公开该接口的实现。
问题是内联函数不能使用内部类。

我基本上想要的是这样的:

/* The interface I want to expose */
interface Params<T> {
    val doc: T
}

/* The implementation I do not want to expose */
internal class ParamsImpl<T> (override val doc: T) : Params<T> 


/* The function */
inline fun <reified T> doSomething(init: Params<T>.() -> Unit) {
    val doc= T::class.java.newInstance()
    val params = ParamsImpl(doc) // Can't compile since ParamsImpl is internal 

    params.init()
}
Run Code Online (Sandbox Code Playgroud)

zsm*_*b13 6

您可以通过添加中间方法来创建ParamsImpl实例来解决此问题:

fun <T> createImpl(doc: T): Params<T> = ParamsImpl(doc)

inline fun <reified T> doSomething(init: Params<T>.() -> Unit) {
    val doc = T::class.java.newInstance()
    val params = createImpl(doc)

    params.init()
}
Run Code Online (Sandbox Code Playgroud)

此方法不必内联(因为您只是将已在该doSomething方法中创建的通用实例传递给它),因此它可以ParamsImpl在其私有实现中使用。

同样重要的是,它的返回类型Params<T>只能将该类型公开给doSomething.


编辑:

要隐藏创建方法,可以将@PublishedApi注解与可见性结合使用internal

@PublishedApi internal fun <T> createImpl(doc: T): Params<T> = ParamsImpl(doc)
Run Code Online (Sandbox Code Playgroud)

这将允许其在inline函数中使用,但对其他用户隐藏。

这意味着在其他模块中,它在 Kotlin 代码中不可见,并且当您尝试从 Java 调用它时,它会给您一个错误(当然,这可以被抑制,但这是 Kotlin 的最佳保证)可以在进行互操作时为您提供其internal可见性)。

如果您更喜欢的话,您还可以使用构造函数并ParamsImpl用 标记类本身。@PublishedApi

  • 哇,那真是太棒了 (2认同)