Встроенная функция не может получить доступ к не-публичному 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 Это интересный подход, однако он может вызвать некоторые проблемы при отладке, хотя я не уверен.

Другие вопросы по тегам