Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
957 views
in Technique[技术] by (71.8m points)

kotlin - Inline function cannot access non-public-API: @PublishedApi vs @Suppress vs @JvmSynthetic

In Kotlin, when I have a non-public member and an inline fun that calls it, there's a compilation error saying:

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

I found several ways to call my function inside a public inline fun, but which is the best way to do it?

Suppose I have a private fun f() { }. Then the options I found are:

  • fun f() { }

    Just make it public. This is the baseline solution, but if the others turn out to have major disadvantages, this can end up the best one.

  • @PublishedApi internal fun f() { }

    Introduced in Kotlin 1.1-M04, the annotation can be applied to an internal member, making it effectively public. The implication I noticed is that any library user will still be able to call it from Java code, that's what I don't like about it.

  • @Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE") inline fun g() { f() }

    Found in the stdlib sources, this annotation seems to suppress the error when applied to the calling function. But what are its limitations? Can it only be used for inline functions? Will the resulting program fail under some circumstances? I tried to call a non-inline function from an inline one with this trick, and it worked, but it looks suspicious.

  • @JvmSynthetic @PublishedApi internal fun f() { }

    Combine the second solution with the synthetic flag in the bytecode. I'm not sure if this is a correct usage of @JvmSynthetic, but this appears to hide the function from Java code, which solves the problem of the @PublishedApi internal.

So, which of these solutions is the best way call a non-public function from a public inline one? What are the downsides of each solution that I don't see?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

@PublishedApi internal is the intended way of exposing non-public API for using in public inline functions.

That @PublishedApi internal member becomes effectively public and its name doesn't get mangled (if you noticed the opposite, please file a bug).

@Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE") is a band-aid workaround in the lack of @PublisedApi based on suppressing an error and therefore isn't recommended. With the introduction of @PublishedApi this suppression is going to be cleaned from stdlib.

@JvmSynthetic combined with @PublishedApi is an interesting approach, however it can cause some problems while debugging, though I'm not sure.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...