Каковы основные различия модификаторов доступа в Java и Kotlin?

Ответ

Модификаторы доступа определяют область видимости классов, функций и свойств. Kotlin вносит ключевые изменения по сравнению с Java.

Сравнительная таблица:

Модификатор Java Kotlin
public Виден везде. Виден везде. Модификатор по умолчанию.
protected Виден в пакете и подклассах (даже из других пакетов). Виден только в подклассах. Не даёт доступа внутри пакета.
internal Отсутствует. Новый модификатор. Виден внутри модуля (набора скомпилированных файлов).
private Виден только внутри класса. Виден внутри класса или файла (для top-level объявлений).
package-private (default) Виден внутри пакета (модификатор не указывается). Отсутствует. Вместо него используйте internal для видимости в модуле или private для файла.

Пример в Kotlin:

// Файл: Network.kt
internal class HttpClient { // Виден в этом модуле
    private val apiKey = "secret" // Виден только в этом классе
    protected fun init() { } // Виден в HttpClient и его наследниках
    fun makeRequest() { } // public по умолчанию, виден везде
}

private fun helper() { } // Видна только в этом файле (Network.kt)

Почему так сделано в Kotlin?

  1. public по умолчанию упрощает код.
  2. internal решает проблему слабой инкапсуляции на уровне пакетов в Java, предоставляя контроль на уровне модуля.
  3. protected становится строже и логичнее, так как пакеты в Kotlin — это в первую очередь способ организации пространств имён, а не механизм контроля доступа.

Ответ 18+ 🔞

Ну, слушай, вот сидишь ты, пишешь на Kotlin, и тут — бац! — вспоминаешь, что модификаторы доступа тут, блядь, не совсем как в Java. А в Java-то ты привык, что public — это публично, private — приватно, и есть этот ёбаный package-private, который нигде не написан, но он есть. И вроде всё просто, но потом начинаешь думать, а кто где виден, и тут — пиздец, волнение ебать.

Так вот, в Kotlin всё по-другому, и, если честно, логичнее. Смотри.

Public — это как в жизни: виден всем, кто посмотрит. И главное — это модификатор по умолчанию! То есть не надо эту хуйню везде писать, язык сам понимает, что ты хотел. Написал fun makeRequest() — и всё, оно уже public. Удобно, блядь.

Protected — а вот тут засада для джавистов. В Java protected виден в пакете и в наследниках. А в Kotlin — только в наследниках, и всё! То есть если ты в одном файле, но не наследник — хуй тебе, а не доступ. Сделано так, потому что пакеты в Kotlin — это просто пространства имён, а не инструмент для скрытия говна. Логично, ёпта.

Internal — это, сука, новинка! Такого в Java вообще не было. Виден внутри модуля. Модуль — это типа набора скомпиленных вместе файлов (проект, библиотека). Идеально, чтобы спрятать какую-нибудь внутреннюю хуйню от пользователей твоей библиотеки, но чтобы внутри проекта все классы могли друг друга ебать. Очень удобная штука, ядрёна вошь.

Private — самый строгий папа. В классе — виден только в классе. А если объявил что-то на уровне файла (типа функцию-хелпер) — то видно будет только в этом файле. Никакой соседний файл в том же пакете не подглядит. Инкапсуляция, блядь, на высоте.

А вот package-private (default из Java) — его в Kotlin просто выпилили, нахуй. Потому что он кривой и непонятный. Вместо него теперь есть internal (для модуля) или private (для файла). И не надо ебать мозг.

Вот смотри на пример, чтобы вообще всё встало на свои места:

// Файл: Network.kt
internal class HttpClient { // Виден во всём нашем модуле, но снаружи — нихуя
    private val apiKey = "secret" // А эту тайну знает только этот класс. Ни жена, ни сосед.
    protected fun init() { } // Увидят только дети этого класса (наследники). Дяде Васе с третьего этажа — нет.
    fun makeRequest() { } // А это — public, видно всем! Потому что модификатор не указан.
}

private fun helper() { } // Эта функция-затычка видна только в этом файле (Network.kt). Как будто её и нет.

И знаешь, почему так переделали? Да потому что в Java с этим package-private был пиздец. Он слабый, неочевидный, и все в итоге лепили public, чтобы не париться. А тут — раз! — internal появился, и можно аккуратно прятать реализацию внутри модуля. И protected стал строже, что тоже правильно. В общем, не зря же эти ребята голову ломали.