1. Введение
Язык программирования Kotlin построен на виртуальной машине Java (JVM). Как таковой, он должен следовать всем правилам, которые устанавливает JVM, включая модификаторы видимости.
Однако есть некоторые тонкие нюансы в том, как язык реализует эти модификаторы в отношении компилятора и способа структурирования нашего кода. В этой статье будут показаны некоторые сходства и различия между Java и Kotlin в этом отношении.
2. Модификаторы видимости
Модификаторы видимости используются для определения того, какие другие элементы кода имеют доступ к изменяемому элементу. Они применяются к некоторым различным элементам кода на разных уровнях области видимости. Способ применения этих правил может незначительно отличаться в зависимости от этих различных применений, что поначалу может сбивать с толку.
2.1. Публичная известность
Наиболее очевидным модификатором является public. Возможно, он наиболее часто используется во всем языке и означает, что нет никаких дополнительных ограничений на то, кто может видеть изменяемый элемент.
В отличие от Java, в Kotlin почти никогда нет необходимости объявлять что–либо как public - это модификатор по умолчанию, используемый, если мы не объявляем другой. Кроме этого, в Kotlin он работает так же, как и в Java.
Если мы применим модификатор public к элементу верхнего уровня - внешнему классу, функции или переменной, объявленным непосредственно внутри пакета, – тогда любой другой код сможет получить к нему доступ. Если мы применим модификатор public к вложенному элементу – внутреннему классу, функции или переменной внутри класса, – то любой код, который может получить доступ к контейнеру, также может получить доступ к этому элементу.
Например:
class Public {
val i = 1
fun doSomething() {
}
}
Класс Public доступен из любой точки всей кодовой базы, “val i” и “fun doSomething()” доступны из всего, что может получить доступ к Public.
2.2. Личная видимость
Другой модификатор, который используется большую часть времени, - private. Это имеет почти прямо противоположное значение public – это означает, что никто не может получить к нему доступ.
На самом деле, в Kotlin это означает, что только код, объявленный внутри той же области, может получить к нему доступ. Это немного отличается от Java просто потому, что Kotlin допускает несколько объявлений верхнего уровня в одном файле - к частному элементу верхнего уровня может быть доступно все остальное в том же файле. В остальном правила те же. Например:
Например:
private class Private {
private val i = 1
private val doSomething() {
}
}
Класс Private доступен только из того же исходного файла, “val i” и “fun doSomething()” доступны только изнутри класса Private.
2.3. Защищенная видимость
Модификатор protected в Kotlin означает, что он строго доступен только объявляющему классу и подклассам. Это то же самое, что большинство людей ожидают от Java, но слегка отличается от того, как работает Java.
В Java модификатор protected также разрешает доступ к элементу из чего-либо еще в том же пакете. Например, учитывая следующий файл класса:
package one;
class A {
protected val i = 1
}
Следующий файл будет нормально работать в Kotlin:
package two;
class B : A() {
fun getValue() : Int {
return i
}
}
Следующий файл будет работать в Java, но не будет работать в Kotlin:
package one;
class C {
fun getValue() : Int {
val a = A()
return a.i
}
}
И следующее не сработало бы ни на Java, ни на Kotlin:
package two;
class D {
fun getValue() : Int {
val a = A()
return a.i
}
}
Кроме того, в Kotlin protected становится видимостью по умолчанию, когда мы переопределяем защищенный элемент из суперкласса. При желании это может быть явно изменено на public, и это основной случай, когда нам нужно будет явно объявить что-либо как public.
2.4. Пакет-Приватный / Видимость по умолчанию
В Java существует модификатор доступа, известный как “package-private” (также называемый “default”). Это используется, когда для элемента не установлен модификатор. Это означает, что любой код в том же пакете может получить к нему доступ, но любой код в другом пакете не может, включая подклассы.
В настоящее время Kotlin вообще не поддерживает этот модификатор, хотя это может измениться в будущем. Причина этого заключается в том, что он не обеспечивает никакой защиты – любой может определить код в том же пакете и получить доступ к нашим элементам даже из другого jar-файла.
2.5. Внутренняя видимость
Kotlin добавляет новый модификатор к параметрам, которые Java в настоящее время не поддерживает – internal. Этот модификатор означает, что любой код, объявленный в том же модуле, который не ограничен иным образом, может получить доступ к этому элементу. (Модуль - это, по сути, Jar-файл.)
Это возможно в Java с использованием таких вещей, как OSGi, но в настоящее время это не является родным для языка. В Java 9 будут представлены некоторые концепции, которые сделают это более достижимым за счет возможности выборочного экспорта общедоступных идентификаторов.
Это дает огромное преимущество при написании API и реализаций. Мы можем писать наши интерфейсы API как общедоступные, нашу основную реализацию как общедоступные классы, а весь вспомогательный код, от которого он зависит, как внутренний. Это означает, что внешний код вынужден проходить через API и не может получить доступ к внутренним компонентам.
Например:
package com.baeldung.modifiers
internal class Internal {
}
class Public {
internal val i = 1
internal fun doSomething() {
}
}
Класс Internal доступен только изнутри того же модуля. “val i” и “fun doSomething()” также доступны только изнутри того же модуля, хотя к классу, внутри которого они находятся, можно получить доступ откуда угодно.
3. Завершение
В большинстве случаев правила использования модификаторов видимости в Kotlin работают так же, как мы ожидали бы от Java. Однако есть существенное отличие, которое заключается во введении внутренней области видимости, что очень полезно для более крупных проектов.
Оригинал статьи: https://www.baeldung.com/kotlin/visibility-modifiers