内联函数无法访问非公共 API:@PublishedApi vs @Suppress vs @JvmSynthetic

Posted

技术标签:

【中文标题】内联函数无法访问非公共 API:@PublishedApi vs @Suppress vs @JvmSynthetic【英文标题】:Inline function cannot access non-public-API: @PublishedApi vs @Suppress vs @JvmSynthetic 【发布时间】:2017-06-13 01:27:34 【问题描述】:

在 Kotlin 中,当我有一个非公共成员和一个调用它的 inline fun 时,会出现编译错误:

错误:(22, 25) Kotlin: Public-API inline function cannot access non-public-API private fun f(): Unit defined in com.example

我找到了几种在公共 inline fun 中调用我的函数的方法,但哪种方法最好?

假设我有一个private fun f() 。那么我找到的选项是:

fun f()

只要公开。这是基准解决方案,但如果其他解决方案有很大的缺点,这可能是最好的解决方案。

@PublishedApi internal fun f()

在Kotlin 1.1-M04 中引入,注释可以应用于内部成员,使其有效地公开。我注意到的含义是任何库用户仍然可以从 Java 代码中调用它,这就是我不喜欢它的地方。

@Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE") inline fun g() f()

在the stdlib sources 中找到,此注解在应用于调用函数时似乎抑制了错误。但它的局限性是什么?只能用于inline功能吗?生成的程序在某些情况下会失败吗?我试图用这个技巧从一个内联函数调用一个非内联函数,它奏效了,但看起来很可疑。

@JvmSynthetic @PublishedApi internal fun f()

将第二个解决方案与字节码中的 synthetic 标志结合起来。我不确定这是否是correct usage of @JvmSynthetic,但这似乎隐藏了Java代码中的函数,从而解决了@PublishedApi internal的问题。

那么,这些解决方案中的哪一个是从公共内联函数调用非公共函数的最佳方式?我看不到的每种解决方案的缺点是什么?

【问题讨论】:

@PublishedApi internal 应该在你的私有成员上声明,而不是在内联函数上 【参考方案1】:

@PublishedApi internal 是公开非公共 API 以在公共内联函数中使用的预期方式。

@PublishedApi internal 成员实际上是公开的,并且其名称​​不会被破坏(如果您注意到相反的情况,请提交错误)。

@Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE") 是一种基于抑制错误而缺少@PublisedApi 的创可贴解决方法,因此不推荐使用。随着@PublishedApi 的引入,这种抑制将从stdlib 中清除。

@JvmSynthetic@PublishedApi 结合使用是一种有趣的方法,但它在调试时可能会导致一些问题,尽管我不确定。

【讨论】:

感谢您的回答。对,现在我看到@PublishedApi internal 保留了完整的名称,我错了。顺便说一句,IDE 是否应该隐藏 @PublishedApi internal 成员以防止其完成或以某种方式阻止他们的使用?而且,出于好奇,@Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE") 有什么问题? @hotkey 任何后续是否将@JvmSynthetic@PublishedApi 结合使用是否会导致任何问题? @StevenJeuris,我没有遇到过,尽管我不能说我使用了很多这种组合。好吧,我旨在检测故障的实验都没有显示任何结果。 @hotkey @Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE") 这不只是为了摆脱警告吧?我的意思是它做了@PublishedApi 打算做的“让成员有效地公开”,对吗?

以上是关于内联函数无法访问非公共 API:@PublishedApi vs @Suppress vs @JvmSynthetic的主要内容,如果未能解决你的问题,请参考以下文章

无法将环境变量传递给 azure 管道 yaml 中的 powershell 脚本(非内联)

Facebook iOS SDK(Graph API) 无法访问公共页面信息

非公共 API 使用警告...阻止上传到 App Store 时的验证?

如何解决“缺少vtable通常意味着第一个非内联虚成员函数没有定义。”

7. 第 7 章 类和对象简介

为啥模块中的这个公共函数无法访问