ПрограммированиеAndroid разработчик

Как работает область видимости (visibility modifiers) в Kotlin: internal, private, protected, public? Чем отличаются модификаторы в различных контекстах — для классов, функций, свойств, объектов, top-level функций и файлов?

Проходите собеседования с ИИ помощником Hintsage

Ответ

В Kotlin существуют следующие модификаторы видимости:

  • public (по умолчанию): элемент виден везде.
  • internal: элемент виден в пределах одного модуля (jar/gradle module и др.).
  • protected: виден только внутри класса и его наследниках.
  • private: виден только в пределах файла или класса.

Особенности:

  • Для top-level функций, свойств и классов: private ограничивает доступ рамками файла, internal — модулем, а public/protected не имеет смысла вне класса.
  • Для членов класса: private — только внутри этого класса, protected — плюс наследники, internal и public — как описано выше.
  • Внутри объекта/компаньон-объекта: аналогично классу.
class MyClass { private val secret = "hidden" protected val id = 42 internal fun foo() {} public fun bar() {} } internal fun moduleFunc() {} private fun fileOnlyFunc() {}

Вопрос с подвохом

"Может ли top-level функция быть protected? Если да — как это работает? Если нет — почему?"

Ответ: Нет, top-level функция не может быть protected, поскольку нет класса, которому принадлежит этот уровень доступа. За это отвечает компилятор – появится ошибка компиляции.

protected fun magic() {} // Ошибка: модификатор protected не разрешён для top-level функций

Примеры реальных ошибок из-за незнания тонкостей темы


История

В fintech-приложении забыли, что internal-модификатор даёт доступ ко всем элементам модуля. В результате при рефакторинге вынесли часть логики в другой gradle-модуль, после чего перестал работать доступ к данным, но разработчики не сразу заметили, так как на этапе компиляции не было ошибок в старых тестах.


История

В мультиплатформенном проекте определили конфиденциальные данные как private свойства в companion object. Оказалось, что эти данные сериализуются и становятся доступны через reflection, потому что были объявлены как val без использования аннотаций, ограничивающих экспорт.


История

На старте мобильного проекта применяли private для top-level функций, полагая, что это ограничит доступ классам-партнёрам. Однако в рамках общего файла с utils эти функции были видны всем, что привело к угрозе утечки информации и непредвиденному использованию их в бизнес-логике.