Встроенная функция не может получить доступ к не-публичному API: @PublishedApi против @Suppress против @JvmSynthetic
В Котлине, когда у меня есть непубличный член и inline fun
это вызывает, есть ошибка компиляции, говорящая:
Ошибка:(22, 25) Котлин: встроенная функция публичного API не может получить доступ к не публичному API
private fun f(): Unit
определяется в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() }
Обнаруженная в источниках stdlib, эта аннотация подавляет ошибку при применении к вызывающей функции. Но каковы его ограничения? Может ли он использоваться только для
inline
функции? Будет ли полученная программа терпеть неудачу при некоторых обстоятельствах? Я попытался вызвать не встроенную функцию из встроенной с помощью этого трюка, и это сработало, но выглядит подозрительно.@JvmSynthetic @PublishedApi internal fun f() { }
Объедините второе решение с синтетическим флагом в байт-коде. Я не уверен, что это правильное использование
@JvmSynthetic
, но это, кажется, скрывает функцию от кода Java, которая решает проблему@PublishedApi internal
,
Итак, какое из этих решений лучше всего назвать непубличной функцией из общедоступной встроенной функции? Каковы недостатки каждого решения, которое я не вижу?
1 ответ
@PublishedApi internal
это предполагаемый способ раскрытия непубличного API для использования в публичных встроенных функциях.
Тот @PublishedApi internal
член становится по сути публичным, и его имя не искажается (если вы заметили обратное, пожалуйста, сообщите об ошибке).
@Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE")
это обходной путь помощи в отсутствии @PublisedApi
основан на подавлении ошибки и поэтому не рекомендуется. С введением @PublishedApi
это подавление будет очищено от stdlib.
@JvmSynthetic
в сочетании с @PublishedApi
Это интересный подход, однако он может вызвать некоторые проблемы при отладке, хотя я не уверен.