TGViewer
Kotlin Kotlin @kotlin_lib · 2.05K subscribers
Post #677 665
🔓 @PublishedApi: Как открыть internal и не покраснеть

В прошлом посте мы говорили, что inline функции нарушают инкапсуляцию. Но что делать, если вам реально нужно обратиться к internal свойству внутри инлайн-функции?

Компилятор ударит по рукам:
"Public-API inline function cannot access non-public declarations"

И он прав. Поскольку код инлайнится в модуль клиента, он физически не сможет вызвать ваш internal метод, так как байт-код клиента ничего не знает о ваших внутренних секретах.

Тут на сцену выходит @PublishedApi.

Смотрим код:


class FastCache {
// Обычный internal - доступен только внутри модуля
internal val backingMap = hashMapOf<String, Any>()

// ❌ ОШИБКА КОМПИЛЯЦИИ:
// Inline функция видна всем, а backingMap - нет.
inline fun getOrPut(key: String, block: () -> Any): Any {
return backingMap.getOrPut(key, block)
}
}



Чтобы это заработало, мы должны сказать компилятору: "Я понимаю риски, сделай это поле публичным в байт-коде, но скрой его в IDE от чужих глаз".

Как надо:


class FastCache {
@PublishedApi // 👈 Магия здесь
internal val backingMap = hashMapOf<String, Any>()

inline fun getOrPut(key: String, block: () -> Any): Any {
return backingMap.getOrPut(key, block) // ✅ Работает!
}
}



Что происходит Under the Hood?

1. В Source Code: Поле остается internal. Если кто-то попробует написать fastCache.backingMap из другого модуля - IDE не подскажет, а компилятор выдаст ошибку.

2. В Bytecode: Поле становится public (или генерируются публичные акцессоры). Это нужно, чтобы заинлайненный код на стороне клиента мог технически выполнить вызов.

⚠️ Warning для архитекторов:
Используя @PublishedApi, вы подписываете кровью контракт о бинарной совместимости.
Если вы в следующей версии библиотеки переименуете или удалите backingMap, код всех клиентов, кто заинлайнил вашу функцию getOrPut, упадет с NoSuchMethodError или NoSuchFieldError в рантайме (даже без перекомпиляции).

Вердикт:
Инструмент мощный для создания zero-overhead оберток, но требует дисциплины. Меняете @PublishedApi поле? Поднимайте мажорную версию библиотеки.

Кто пишет свои либы, часто приходится так "оголять" кишки классов?

✍️ @kotlin_lib
  • 👍 3
More from @kotlin_lib
  1. Aug 26, 2026🚧 Ваш Mutex тормозит корутины. Как перестать лочить и начать жить Вы пишете многопоточный…
  2. Jul 25, 2026🚀 Подборка полезных IT каналов в Max Системное администрирование, DevOps 📌 https://max.r…
  3. Jul 1, 2026🌪 Ваша дата в опасности: flatMapConcat vs Merge vs Latest Вам нужно взять поток ID-шников…
  4. Jun 24, 2026🤖 Android-приложение — это не только красивый экран. За ним стоят работа с внешним API, з…
  5. Jun 23, 2026🔮 Убийца бойлерплейта: Встречайте Context Parameters (Kotlin 2.x) Мы так привыкли к Depen…
  6. Jun 3, 2026Яндекс обновил Yandex Mobile Ads SDK для монетизации мобильных приложений — и это интересн…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →