Переменные и константы. Ключевые слова var , val , const
В языке Kotlin фундаментальной единицей любой программы являются переменные и константы. Они используются для хранения данных (значений) в программе.
Данные описываются соответствующими типами. А следовательно, переменные и константы имеют определенный тип. Более подробно о типах данных можно прочитать здесь .
Каждая переменная или константа сохраняет некоторое значение определенного типа. Тип данных определяет размер ячейки памяти, которая будет выделена для объявленной переменной или константы.
В зависимости от алгоритма решения задачи, в программе может использоваться любое количество переменных или констант.
Каждая переменная или константа имеет имя, которое задается при ее объявлении. Имя переменной выбирается таким образом, чтобы оно соответствовало назначению этой переменной в программе. Например, количество элементов целесообразно обозначить именами length или count, а объем какого-то объекта именем volume.
Правильный выбор имен в программе дает следующие взаимосвязанные преимущества:
- повышается читабельность программы;
- облегчается сопровождение программы другими программистами;
- снижается риск допущения ошибок, которые могут возникнуть в результате путаницы в именах.
В программе можно объявлять переменные двух видов:
- изменяемые переменные (ссылки), которые объявляются с использованием ключеового слова var . Значение такой переменной в программе можно изменять многократно;
- неизменяемые переменные (ссылки) или только читаемые переменные. В этом случае используется ключевое слово val . Такой переменной нельзя присвоить значение после инициализации (переменной присваивается значение только один раз). Эти переменные соответствуют final -переменным языка Java.
2. Синтаксис объявления изменяемой переменной. Ключове слово var
Любая переменная в программе на языке Kotlin может быть объявлена одним из двух способов:
Синтаксис (общая форма) объявления переменной без инициализации имеет следующий вид:
var VariableName: Type
- VariableName — имя переменной;
- Type — тип переменной ( Int , Double и т.д.). Более подробно о базовых типа данных можно прочитать здесь .
После такого объявления, переменной можно присваивать значения типа Type или иного типа, совместимого с типом Type .
Синтаксис объявления переменной с инициализацией позволяет сразу присвоить нужное значение переменной
var VariableName: Type = Value
- VariableName — имя переменной, которая будет сохранять данные типа Type ;
- Value — некоторое значение. Это значение может быть литералом, именем другой переменной или константы, результатом возврата из функции.
Если переменной VariableName присвоить значение типа, который не является типом Type или несовместим с ним, то компилятор выдаст ошибку несовместимости типов.
3. Пример объявления переменных различных типов с использованием ключевого слова var
fun main(args:Array) < // Ключевое слово var // 1. Объявление переменных без инициализации // 1.1. Переменная с именем x типа Short var x : Short // позже переменной x можно присваивать некоторое значение типа Short x = 100 // 1.2. Переменная y типа String (строка) var y : String y = "bestprog.net" // 1.3. Переменная z типа Float var z : Float z = 1234.56f println("x color: #008000;">"y color: #008000;">"z color: #808080;"> // 2. Объявление переменных с инициализацией // Объявить переменную a типа Double // и присвоить ей значение 12.88 var a:Double = 12.88 // Объявить переменную b типа Int // и присвоить ей целую часть переменной a var b:Int = a.toInt() // b = 12 // Объявить переменную c типа Char и присвоить ей значение var c:Char = '+'; // Объявить переменную d типа String // и присвоить ей строку var d:String = "Hello world!"; println("a color: #008000;">"b color: #008000;">"c color: #008000;">"d color: #008000;">// 1.2. Переменная y типа String (строка) var y : String // Попытка присвоить переменной y числовое значение y = 120 // ошибка компиляции .
то компилятор выдаст ошибку
Error:(17, 9) Kotlin: The integer literal does not conform to the expected type String
Это логично, поскольку переменная y при объявлении имеет тип String (строка) и присвоить ей числовое значение невозможно.
4. Переменные, доступные только для чтения (неизменяемые переменные). Использование ключевого слова val в объявлении переменной. Синтаксис
Язык Kotlin позволяет использовать переменные, доступные только для чтения. Эти переменные имеют постоянные значения в течение всего времени выполнения программы. Эти переменные не являются константами. Они могут получать значение только один раз.
Например, если программа работает с некоторым файлом, то допускается задать имя файла один раз в начале программы, чтобы затем использовать этот файл многократно.
Если переменная, предназначеная только для чтения, получила начальное значение, повторная попытка изменения этого значения вызовет ошибку компиляции.
Как и в случае с var-переменными (см. п. 2) в языке Kotlin допускается объявлять переменные, предназначенные только для чтения, одним из двух способов:
Общая форма (синтаксис) объявления переменной, предназначенной только для чтения, без начальной инициализации следующая
val VarName : Type
После такого объявления, переменной можно присвоить новое значение только один раз
здесь Value – некоторое значение, литерал, переменная, константа или результат возврата из функции.
Соответственно, синтаксис объявления переменной, предназначенной только для чтения, с начальной инициализацией следующий
val VarName : Type = Value
5. Пример объявления и использования переменных, доступных только для чтения
fun main(args:Array) < // Ключевое слово val // 1. Объявление без инициализации // 1.1. Для типа Long val a : Long a = 1_000_000_000_000_000_000 //a = 300 // здесь ошибка, повторно изменять переменную a запрещено // 1.2. Для типа Char val c : Char c = '&' println("a color: #008000;">"c color: #808080;"> // 2.1. Объявление с инициализацией // 2.2. Для типа Byte val d : Byte = 15 // 2.2. Для типа String val fileName = "myfile.txt" println("d color: #008000;">"fileName color: #0000ff;">300 // здесь ошибка, повторно изменять переменную a запрещено
то компилятор выдаст ошибку
Error:(11, 5) Kotlin: Val cannot be reassigned
6. Синтаксис объявления константы. Ключевое слово const
В языке Kotlin допускается объявлять константы — имена, которые получают неизменяемые значения в течение выполнения программы. Это значения, которые никогда не изменяются в программе. Их еще называют константы времени компиляции, так как значения константам присваивается при компиляции (в момент, когда программа компилируется).
Константы могут получать значение только базовых типов: Int , Double , Float , Long , Short , Byte , Char , String , Boolean .
Для объявления константы используется модификатор const .
Чтобы в программе объявить константу нужно, чтобы эта константа была в глобальной области видимости. Объявить константу в локальной области видимости (в теле функции) не удастся. На попытку объявления константы в теле функции (в пределах фигурных скобок <> ) компилятор выдаст ошибку.
Синтаксис объявления константы имеет две разновидности:
- с явным указанием типа константы;
- без явного указания типа константы. В этом случае тип константы определяется типом получаемого значения (литерала).
Синтаксис объявления константы с явным указанием типа следующий
const val ConstantName : Type = Value
- ConstantName – имя константы. При использовании этого имени в программе, будет подставляться значение Value ;
- Value – значение, которое получает константа.
Синтаксис объявления константы без явного задания типа имеет вид
const val ConstantName = Value
7. Примеры объявления констант
Константы объявляются в глобальной области видимости, то есть за пределами функции main() или любой другой функции.
// Объявление константы - глобальная область видимости // 1. Без явного указания типа const val Pi = 3.1415; // константа типа Double const val Language = "Kotlin" // константа типа String // С указанием типа const val Max : Int = 200 // константа типа Int // fun MyFun() < // Здесь запрещено объявлять константы // . > fun main(args:Array) < // В локальной области запрещено объявлять константу // Использование констант Pi, Language, Max в функции main() println("Pi color: #008000;">"Language color: #008000;">"Max color: #0000ff;">main()fun main(args:Array) < // В локальной области запрещено объявлять константу const val Radius = 1.5 // ошибка компиляции // . >то компилятор сгенерирует ошибку
Error:(22, 5) Kotlin: Modifier 'const' is not applicable to 'local variable'
8. Что такое статическая типизация?
В языке Kotlin реализована статическая типизация. Это проверка компилятором исходного кода, написанного программистом, на корректность и совместимость типов.
В контексте сказанного различают статическую проверку совместимости типов. Эта проверка позволяет увидеть ошибки еще до компиляции кода.
9. Что такое автоматическое определение типов?
Автоматическое определение типа — это определение типа переменной или константы на основе значения, которое она получает при ее объявлении.
Каждое значение, которое присваивается переменной или константе, имеет определенный тип. Если в объявлении переменной или константы не указывать их тип, то эта переменная или константа примет тип значения которое она получает.
Пример. Объявляются переменные и константы которые получают различные типы на основе получаемых значений.
// Объявление константы типа Float const val constFloat = 1.777F // 1.777F - значение типу Float // Объявление константы типа Long const val Max = 10000000000L . // Объявление переменной типа Char var c1 = 'Z' val c2 = 'X' // Объявление переменной типа Double var a = 2.5 var b = 3.8 val c = 2.7Связанные темы
Kotlin blog
Если значение свойства только для чтения известно во время компиляции, отметьте его как постоянную времени компиляции с помощью модификатора const. Такие свойства должны соответствовать следующим требованиям:
- Верхний уровень или член объявления объекта или сопутствующий объект (companion object).
- Инициализируется значением типа String или примитивным типом
- Нет специального получателя
Такие свойства можно использовать в аннотациях:
const val SUBSYSTEM_DEPRECATED: String = "This subsystem is deprecated" @Deprecated(SUBSYSTEM_DEPRECATED) fun foo()
Свойства и переменные с поздней инициализацией
Обычно свойства, объявленные как имеющие ненулевой тип, должны быть инициализированы в конструкторе. Однако довольно часто это не удобно. Например, свойства могут быть инициализированы с помощью внедрения зависимостей или с помощью метода настройки модульного теста. В этом случае вы не можете указать в конструкторе инициализатор, отличный от null, но вы все равно хотите избежать проверки null при ссылке на свойство внутри тела класса.
Чтобы справиться с этим случаем, вы можете пометить свойство модификатором lateinit:
public class MyTest < lateinit var subject: TestSubject @SetUp fun setup() < subject = TestSubject() >@Test fun test() < subject.method() // разыменование напрямую >>
Модификатор можно использовать для свойств var, объявленных внутри тела класса (не в основном конструкторе, и только тогда, когда свойство не имеет настраиваемого средства получения или установки) и, начиная с Kotlin 1.2, для свойств верхнего уровня и локальных переменных. Тип свойства или переменной не должен быть нулевым и не должен быть примитивным типом.
Доступ к свойству lateinit до его инициализации вызывает специальное исключение, которое четко определяет свойство, к которому осуществляется доступ, и тот факт, что оно не было инициализировано.
Проверка инициализации переменной lateinit (начиная с версии 1.2)
Чтобы проверить, инициализирована ли уже переменная lateinit, используйте .isInitialized для ссылки на это свойство:
Эта проверка доступна только для свойств, которые лексически доступны, т. н. объявлены в том же типе, или в одном из внешних типов, или на верхнем уровне в том же файле.
Делегированные свойства
Наиболее распространенный вид свойств просто считывает (и, возможно, записывает) резервное поле. С другой стороны, с помощью настраиваемых геттеров и сеттеров можно реализовать любое поведение свойства. Где-то посередине есть определенные общие закономерности того, как собственность может работать. Несколько примеров: отложенные значения, чтение с карты по заданному ключу, доступ к базе данных, уведомление слушателя о доступе и т. д.
Такое обычное поведение можно реализовать в виде библиотек с использованием делегированных свойств.