Синтаксис и пунктуация в Kotlin
Откуда взялся синтаксис
По описанию языка, синтаксис — синтез двух ветвей:
- от C, C++, Java — блоки кода в фигурных скобках, привычная императивная структура;
- от ML (через Scala) — постфиксные типы (
имя — Тип), ключевые словаfunиval, вывод типов.
Точка с запятой не обязательна (как в Scala, Groovy и JavaScript): в большинстве случаев достаточно перевода строки. Поддерживаются процедурный стиль с функциями и ООП. Точка входа — fun main, в том числе с массивом аргументов командной строки. Строки допускают интерполяцию ("Hello, $name!"), как в Perl и shell.
Типичный минимальный пример (как в официальных материалах):
fun main() {
val scope = "world"
println("Hello, $scope!")
}
Работа с nullable — оператор Элвиса и цепочки safe call:
fun sayHello(maybe: String?, neverNull: Int) {
val name: String = maybe ?: "stranger"
println("Hello, $name")
}
// null, если любое звено цепочки null
val result = foo?.bar()?.baz()
Подробнее о типах — Типы данных, о null — справочник.
Названия знаков по-английски и по-русски: Знаки препинания и символы в IT.
Знаки препинания
Два важных вопроса, которые мучают начинающих программистов:
- Когда использовать кавычки двойные (
"), одинарные ('), а когда апострофы (’)? - Когда использовать точки (
.), запятые (,) и точку с запятой (;)?
Двойные (") — обычные строки:
val name = "Alice"
Разбор:
- Фрагмент показывает исполняемый сценарий: здесь важен порядок шагов и состояние между вызовами.
valфиксирует ссылку после инициализации и делает поведение участка более предсказуемым.- Операции присваивания связывают вычисленные значения с переменными и делают промежуточные шаги явно читаемыми.
- Фрагмент полезно читать сверху вниз: каждая строка подготавливает контекст для следующего шага.
- В практическом коде этот шаблон обычно оборачивают обработкой ошибок и проверкой входных данных.
Тройные (""") — многострочные строки:
val text = """Line 1
Line 2"""
Разбор:
- Фрагмент показывает исполняемый сценарий: здесь важен порядок шагов и состояние между вызовами.
valфиксирует ссылку после инициализации и делает поведение участка более предсказуемым.- Операции присваивания связывают вычисленные значения с переменными и делают промежуточные шаги явно читаемыми.
- Фрагмент полезно читать сверху вниз: каждая строка подготавливает контекст для следующего шага.
- В практическом коде этот шаблон обычно оборачивают обработкой ошибок и проверкой входных данных.
Интерполяция внутри двойных кавычек:
val age = 25
println("Age: $age")
Разбор:
- Фрагмент показывает исполняемый сценарий: здесь важен порядок шагов и состояние между вызовами.
valфиксирует ссылку после инициализации и делает поведение участка более предсказуемым.printlnиспользуется как быстрая проверка результата и помогает увидеть фактический ход выполнения.- Интерполяция
${...}или$nameв строках делает вывод компактным и избавляет от ручной конкатенации. - Ключевые вызовы во фрагменте (
println) формируют основной поток выполнения и обмена данными. - Операции присваивания связывают вычисленные значения с переменными и делают промежуточные шаги явно читаемыми.
Одинарные (') — только для одиночного символа (Char):
val letter = 'A'
Разбор:
- Фрагмент показывает исполняемый сценарий: здесь важен порядок шагов и состояние между вызовами.
valфиксирует ссылку после инициализации и делает поведение участка более предсказуемым.- Операции присваивания связывают вычисленные значения с переменными и делают промежуточные шаги явно читаемыми.
- Фрагмент полезно читать сверху вниз: каждая строка подготавливает контекст для следующего шага.
- В практическом коде этот шаблон обычно оборачивают обработкой ошибок и проверкой входных данных.
Апострофы (’) — не поддерживаются.
Точка (.) используется для вызова методов и свойств:
val list = listOf(1, 2, 3)
println(list.size)
Разбор:
- Фрагмент показывает исполняемый сценарий: здесь важен порядок шагов и состояние между вызовами.
valфиксирует ссылку после инициализации и делает поведение участка более предсказуемым.printlnиспользуется как быстрая проверка результата и помогает увидеть фактический ход выполнения.- Ключевые вызовы во фрагменте (
listOf, println) формируют основной поток выполнения и обмена данными. - Операции присваивания связывают вычисленные значения с переменными и делают промежуточные шаги явно читаемыми.
- В практическом коде этот шаблон обычно оборачивают обработкой ошибок и проверкой входных данных.
Запятая (,) для разделения параметров, элементов списка и т. д.:
val numbers = listOf(1, 2, 3)
fun greet(name: String, age: Int)
Разбор:
- Фрагмент показывает исполняемый сценарий: здесь важен порядок шагов и состояние между вызовами.
funвыделяет именованные блоки логики, что упрощает повторное использование и тестирование кода.valфиксирует ссылку после инициализации и делает поведение участка более предсказуемым.- Ключевые вызовы во фрагменте (
listOf, greet) формируют основной поток выполнения и обмена данными. - Операции присваивания связывают вычисленные значения с переменными и делают промежуточные шаги явно читаемыми.
- В практическом коде этот шаблон обычно оборачивают обработкой ошибок и проверкой входных данных.
Точка с запятой (;) не требуется в Kotlin. Используется только если нужно писать несколько выражений в одной строке:
val x = 5; val y = 10
Разбор:
- Фрагмент показывает исполняемый сценарий: здесь важен порядок шагов и состояние между вызовами.
valфиксирует ссылку после инициализации и делает поведение участка более предсказуемым.- Операции присваивания связывают вычисленные значения с переменными и делают промежуточные шаги явно читаемыми.
- Фрагмент полезно читать сверху вниз: каждая строка подготавливает контекст для следующего шага.
- В практическом коде этот шаблон обычно оборачивают обработкой ошибок и проверкой входных данных.
Нижние подчеркивания в Kotlin бывают для стиля и для синтаксиса:
_name - соглашение, но не общепринятое. Приватные поля в Kotlin выглядят как private val logger, а _ используется для полей редко.
_ может быть как игнорирование при деструктуризации:
val (name, _, age) = person
Разбор:
- Фрагмент показывает исполняемый сценарий: здесь важен порядок шагов и состояние между вызовами.
valфиксирует ссылку после инициализации и делает поведение участка более предсказуемым.- Ключевые вызовы во фрагменте (
val) формируют основной поток выполнения и обмена данными. - Операции присваивания связывают вычисленные значения с переменными и делают промежуточные шаги явно читаемыми.
- Фрагмент полезно читать сверху вниз: каждая строка подготавливает контекст для следующего шага.
- В практическом коде этот шаблон обычно оборачивают обработкой ошибок и проверкой входных данных.
и как разделитель в числах:
val million = 1_000_000
Разбор:
- Фрагмент показывает исполняемый сценарий: здесь важен порядок шагов и состояние между вызовами.
valфиксирует ссылку после инициализации и делает поведение участка более предсказуемым.- Операции присваивания связывают вычисленные значения с переменными и делают промежуточные шаги явно читаемыми.
- Фрагмент полезно читать сверху вниз: каждая строка подготавливает контекст для следующего шага.
- В практическом коде этот шаблон обычно оборачивают обработкой ошибок и проверкой входных данных.
Символы "|" и "||" в JavaScript, C#, Java, C++ и Kotlin использутся в общем порядке:
| — это побитовое ИЛИ (bitwise OR): оператор обрабатывает каждый бит целого, в отличие от логического ||.
К примеру, метод(значениеА | значениеБ);
В условиях это логическое ИЛИ, но без сокращённого вычисления.
if (методА() | методБ()) - вызовет и методА, и методБ, даже если методА - true.
|| - логическое ИЛИ (с сокращённым вычислением), можно назвать исключающим.
допустим return a || b - если a true, то b не вернется/не вычислится.
if (a() || b()) { ... } // b() не вызывается, если a() == true
Разбор:
- Фрагмент показывает исполняемый сценарий: здесь важен порядок шагов и состояние между вызовами.
ifвыполняет проверку условия и направляет выполнение в соответствующую ветку.- Ключевые вызовы во фрагменте (
a, b) формируют основной поток выполнения и обмена данными. - Операции присваивания связывают вычисленные значения с переменными и делают промежуточные шаги явно читаемыми.
- Границы блоков в фигурных скобках помогают сразу увидеть области видимости и жизненный цикл локальных переменных.
- В практическом коде этот шаблон обычно оборачивают обработкой ошибок и проверкой входных данных.
Дополнительные сниппеты
val user = "admin"
val role = if (user == "admin") "full-access" else "read-only"
println("Role: $role")
Разбор:
- Первая строка задаёт исходные данные, а вторая вычисляет производное значение через
if-выражение. ifв Kotlin возвращает результат, поэтому его удобно использовать прямо в присваивании.val roleделает вычисленный результат неизменяемым и снижает риск случайного изменения роли.printlnвыводит итог в консоль и помогает быстро проверить поведение условия.- Интерполяция
$roleвставляет значение в строку без ручной сборки через+. - Сценарий отражает типовой шаблон: входные данные → вычисление правила → вывод результата.
val text = "kotlin"
val normalized = text.uppercase().replace("K", "C")
println(normalized)
Разбор:
- Пример показывает цепочку вызовов у строки, где каждый шаг возвращает новое значение.
uppercase()переводит строку в верхний регистр, после чегоreplace()заменяет конкретный символ.- Kotlin-строки неизменяемы, поэтому исходная переменная
textсохраняет первоначальное значение. - Новое значение сохраняется в
normalized, что отделяет исходные данные от результата преобразования. - Такой стиль делает обработку текста линейной и читаемой: преобразования идут сверху вниз без скрытых эффектов.