Kotlin область видимости переменных

Урок 16: Модификаторы доступа (видимости) в Kotlin. public, private, protected, internal

Модификаторы доступа это определенные ключевые слова в языке, с помощью которых можно устанавливать уровень видимости для класса, переменной или метода. Под уровнем видимости я имею в виду буквально будет ли видна переменная или функция, из другого класса или пакета. Расширение или ограничение видимости данных нужно для правильного проектирования архитектуры программы, соблюдая основные принципы объектно-ориентированного программирования. В том числе инкапсуляцию. О об этом принципе ООП будет чуть ниже.

Сейчас пройдемся по основным модификаторам доступа:

public. В Kotlin этот модификатор проставляется по умолчанию для всех классов, методов или переменных. Как написано в неофициальной русскоязычной документации по языку: “Код данного объявления будет виден из космоса”. То есть все данные будут публичными, если не указывать никакой модификатор. И доступ к ним возможен из любого места проекта. Другими словами обратиться к этим данным можно из любого класса или пакета, импортировав их в требуемый файл.

private. Объявленные данные с этим модификатором доступны только в рамках файла. Либо в рамках класса, если данные помечены как приватные внутри него.

protected. Данные с этим модификатором видны в классе, в котором они определены и в классах-наследниках.

internal. Данные с этим модификатором доступны в любой части модуля, в котором они определены. С модулями будем разбираться в рамках серии уроков по Android, поэтому пока по нему примеров не будет.

Применение

Переходим к практике. Описывать будем сущность путеводителя для путешествующих автостопом по Галактике.

Читайте также:  Php pdo insert примеры

Создаем класс HitchhikersGuide.

Итак, в Kotlin, не указывая модификатор, элемент по умолчанию становится публичным. Если навести курсор на название класса, увидим его полное объявление с модификатором public. То же самое увидим, если объявим поле и функцию в теле класса. Переменная title и метод chooseArticle().

Причем можно принудительно добавить ключевое слово public перед объявлением и ничего принципиально не изменится. Только то, что студия разработки подсветит серым и предложит удалить его как повторяющийся модификатор. Воспользуемся этим предложением.

Мы имеем доступ ко всем публичным данным класса, так и задумано. С помощью модификатора private можно ограничивать этот доступ до уровня файла или класса. Например, сделаем приватным поле title. Теперь это поле доступно только в рамках класса HitchhikersGuide. Соответственно, результат будет такой же, если сделать приватным и метод.

При наведении на ошибку в рабочем файле нам говорят, что нет доступа к приватной переменной или методу. Если открыть контекстное меню со всеми предлагаемыми вариантами исправления, увидим две подсказки. Можно сделать данные публичными (просто удалив ключевое слово private) или пометить их как internal. У нас сейчас нет разделения на модули и все происходящее считаем единым целым модулем main. Поэтому эти данные будут видны везде. Модуль вы можете увидеть слева в иерархии проекта, он по умолчанию называется main и подсвечивается квадратом на папке.

Также приватным можно объявить и весь класс. Сделаем это и уже будет невозможным создание объекта. А также автоматически закрывается доступ ко всей внутрянке класса.

Область видимости

Закомментируем пока этот код, оставим публичным класс и переменную title. Переместимся в файл HitchhikersGuide. Для демонстрации создадим здесь другой вспомогательный класс Support. Внутри сделаем публичную функцию в которой будем получать и распечатывать данные класса HitchhikersGuide. Выведем в консоль название класса и значение переменной title. Как видите, метод chooseArticle() недоступен – его область видимости ограничивается классом.

Для примера объявим еще одну переменную, но вне классов. С рандомным названием и содержанием типа supportInfo, и распечатаем ее. Обратите внимание, что это также приватная переменная, но ее область видимости распространяется на весь текущий файл. В рабочем файле она также будет уже не видна.

Инкапсуляция

Такое ограничение видимости есть инкапсуляция. Определение инкапсуляции можно дать такое – это упаковка данных и функций, для работы с ними, внутри общего компонента. Это механизм для пресечения прямого доступа извне к определенным атрибутам компонента.

Без инкапсуляции можно иметь прямой доступ к переменной класса, например, из другого класса. Таким образом можно случайно нарушить логику работы отдельного компонента программы.

Чтобы обеспечить непрямой доступ к данным другого класса, можно использовать публичные методы. Они будут обращаться к внутренним приватным переменным и отдавать значения. Например, добавим в класс приватную переменную, которая будет по умолчанию хранить количество разделов гайда numberOfPages. Тут же добавим публичный метод getNumberOfPages(), который будет возвращать данные объявленной ранее переменной. Если говорить точнее, будет отдавать значение переменной numberOfPages у созданного ранее экземпляра.

class HitchhikersGuide() < var title = "Don't panic" private val numberOfPages = 9999 private fun chooseArticle() < println("Open catalog") >fun getNumberOfPages() = numberOfPages >

Теперь в рабочем файле можем получить это значение, вызвав getNumberOfPages() через экземпляр класса, в котором он находится.

val guide = HitchhikersGuide() println(guide.getNumberOfPages())

Таким же образом полю можно и задавать значения не напрямую. Сделаем переменную изменяемой и допишем новый метод setNumberOfPages(), который будет принимать новое значение количества страниц и присваивать его соответствующему полю.

class HitchhikersGuide() < var title = "Don't panic" private var numberOfPages = 9999 private fun chooseArticle() < println("Open catalog") >fun getNumberOfPages() = numberOfPages fun setNumberOfPages(number: Int) < numberOfPages = number >>

Вызовем этот метод в рабочем файле, в параметры положим новое целочисленное значение. Распечатаем его заново. Значение количества страниц для этого объекта изменено.

val guide = HitchhikersGuide() println(guide.getNumberOfPages()) guide.getNumberOfPages() guide.setNumberOfPages(4200) println(guide.getNumberOfPages())

Подытожим. Вся реализация закрыта за методами, которые позволяют получить доступ к данным внутри компонента. В случае с Котлин речь идет не только о методах, но и о свойствах. Соблюдая правила инкапсуляции можно настроить получение доступа к данным от одного конкретного объекта (и только от него) к другому, такому же уникальному. Извне напрямую к полю обращаться нельзя. Мы получаем возможность внутри менять внутренности класса, не задействуя внешний интерфейс и не боясь сломать логику во вне. Таким образом мы инкапсулировали (оградили) кусок кода внутри класса от внешнего мира.

И так тихо сапой мы подобрались к теме сеттеров и геттеров. Об этом в следующем уроке. А проверить себя в теме модификаторов можно с помощью тестов в боте под видео.

Для тех, кто собрался стать Android-разработчиком

Пошаговая
схема

Описание процесса обучения от основ Kotlin до Android-разработчика

Бесплатные
уроки

Авторский бесплатный курс по основам языка программирования Kotlin

Обучающий
бот

Тренажер и самоучитель по Котлин – бесплатные тесты и практика

Источник

Visibility modifiers

Classes, objects, interfaces, constructors, and functions, as well as properties and their setters, can have visibility modifiers. Getters always have the same visibility as their properties.

There are four visibility modifiers in Kotlin: private , protected , internal , and public . The default visibility is public .

On this page, you’ll learn how the modifiers apply to different types of declaring scopes.

Packages

Functions, properties, classes, objects, and interfaces can be declared at the «top-level» directly inside a package:

  • If you don’t use a visibility modifier, public is used by default, which means that your declarations will be visible everywhere.
  • If you mark a declaration as private , it will only be visible inside the file that contains the declaration.
  • If you mark it as internal , it will be visible everywhere in the same module.
  • The protected modifier is not available for top-level declarations.

To use a visible top-level declaration from another package, you should import it.

// file name: example.kt package foo private fun foo() < . >// visible inside example.kt public var bar: Int = 5 // property is visible everywhere private set // setter is visible only in example.kt internal val baz = 6 // visible inside the same module

Class members

For members declared inside a class:

  • private means that the member is visible inside this class only (including all its members).
  • protected means that the member has the same visibility as one marked as private , but that it is also visible in subclasses.
  • internal means that any client inside this module who sees the declaring class sees its internal members.
  • public means that any client who sees the declaring class sees its public members.

In Kotlin, an outer class does not see private members of its inner classes.

If you override a protected or an internal member and do not specify the visibility explicitly, the overriding member will also have the same visibility as the original.

Constructors

Use the following syntax to specify the visibility of the primary constructor of a class:

You need to add an explicit constructor keyword.

Here the constructor is private. By default, all constructors are public , which effectively amounts to them being visible everywhere the class is visible (this means that a constructor of an internal class is only visible within the same module).

Local declarations

Local variables, functions, and classes can’t have visibility modifiers.

Modules

The internal visibility modifier means that the member is visible within the same module. More specifically, a module is a set of Kotlin files compiled together, for example:

  • An IntelliJ IDEA module.
  • A Maven project.
  • A Gradle source set (with the exception that the test source set can access the internal declarations of main ).
  • A set of files compiled with one invocation of the Ant task.

Источник

Оцените статью