web-dev-qa-db-ja.com

インライン関数は非公開APIにアクセスできません:@PublishedApi vs @Suppress vs @JvmSynthetic

Kotlinで、非公開メンバーとそれを呼び出す_inline fun_がある場合、次のようなコンパイルエラーが発生します。

エラー:(22、25)Kotlin:パブリックAPIインライン関数は_com.example_で定義された非パブリックAPI private fun f(): Unitにアクセスできません

Public _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() }

    stdlibソース で見つかりました。このアノテーションは、呼び出し元の関数に適用されたときにエラーを抑制しているようです。しかし、その制限は何ですか? inline関数にのみ使用できますか?結果のプログラムは、特定の状況下で失敗しますか?このトリックでインライン関数から非インライン関数を呼び出そうとしましたが、うまくいきましたが、疑わしいようです。

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

    2番目のソリューションをバイトコードのsyntheticフラグと組み合わせます。これが _@JvmSynthetic_ の正しい使用法かどうかはわかりませんが、これは関数をJavaコードから隠しているように見えます。これにより、次の問題が解決されます。 _@PublishedApi internal_。

では、これらのソリューションのどれが、パブリックインライン関数から非パブリック関数を呼び出す最良の方法ですか?私が見ない各ソリューションの欠点は何ですか?

23
hotkey

_@PublishedApi internal_は、パブリックインライン関数で使用するための非パブリックAPIを公開するための意図された方法です。

その_@PublishedApi internal_メンバーは事実上公開され、その名前はしません混乱します(反対に気付いた場合は、バグを報告してください)。

@Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE")は、エラーの抑制に基づく_@PublisedApi_がない場合のバンドエイドの回避策であるため、お勧めしません。 _@PublishedApi_の導入により、この抑制はstdlibから削除されます。

_@JvmSynthetic_と_@PublishedApi_の組み合わせは興味深いアプローチですが、デバッグ中に問題が発生する可能性がありますが、よくわかりません。

19
Ilya