Переменные
Изучаем переменные в Dart. Ниже пример создания и инициализации переменной:
var name = 'Jack';Code language: JavaScript (javascript)
Переменные хранят ссылки. Переменная с именем name содержит ссылку на строковый объект со значением «Bob».
Ссылка — это адрес в памяти. Для удобства хранения данных каждой области памяти присваивается уникальный адрес, как номер дома на улице.

Компилятор автоматически определяет тип name как String, но тип можно указать вручную для изменения вывода. Если переменная должна хранить объекты разных типов, объявите её тип как Object (при необходимости используйте dynamic).
Object name = 'Jack';Code language: JavaScript (javascript)
Другой вариант — явное указание типа (например, мы знаем, что имя — текст, поэтому сразу указываем строковый тип String):
String name = 'Jack';Code language: JavaScript (javascript)
Безопасность нулевых значений (Null safety)
Безопасность нулевых значений предотвращает ошибки при случайном обращении к переменным со значением null, такие ошибки называются ошибками разыменования нуля (null dereference error). Ошибка возникает, если обратиться к свойству или вызвать метод выражения, результат которого равен null.
Есть исключение: если сам null поддерживает данное свойство или метод (например toString(), hashCode), ошибки не будет. Благодаря null safety компилятор Dart обнаруживает подобные потенциальные ошибки на этапе компиляции.
Разработчики с опытом знают, что ошибки нулевых ссылок встречаются очень часто. Если предотвратить их уже на стадии компиляции, стабильность и надёжность программы значительно вырастут.
Пример: допустим, нужно получить абсолютное значение переменной i типа int. Если i равно null, вызов i.abs() вызовет ошибку разыменования нуля. В других языках такая ошибка появится только во время выполнения программы; компилятор Dart сразу заблокирует такой недопустимый вызов и выявит проблему заранее.
Три ключевые изменения из-за null safety:
1 Типы, допускающие null: при указании типа можно разрешить или запретить хранение значения null, достаточно добавить вопросительный знак в конец типа.
String? name // Тип с поддержкой null: значение может быть null или строка
String name // Тип без поддержки null: не может принимать null, только строкиCode language: JavaScript (javascript)
Во многих языках переменная string name может хранить null, но в Dart это запрещено. Чтобы разрешить хранение null используйте тип string?.
2 Переменные должны быть инициализированы перед использованием. Переменные с типом, допускающим null, по умолчанию равны null — это автоматическая инициализация; типы без поддержки null не имеют значения по умолчанию, их обязательно нужно инициализировать вручную. Dart запрещает обращаться к неинициализированным переменным, чтобы исключить ошибки.
void main() {
int year; // Ошибка: неинициализированная переменная без поддержки null
print(year); // Ошибка компиляции: переменная year не инициализирована
}
Code language: Dart (dart)
При компиляции этого кода возникнет ошибка
C:\dartdemo\firstdart>dart run
Building package executable...
Failed to build firstdart:firstdart:
bin/firstdart.dart:7:9: Error: Non-nullable variable 'year' must be assigned before it can be used.
print(year); // Ошибка компиляции: переменная year не инициализирована
^^^^Code language: JavaScript (javascript)
А переменные с поддержкой null допускают такой код:
void main() {
int? age; // Переменная с поддержкой null, значение по умолчанию null
print(age); // Выведет null без ошибок
//age = 18; // Ручное присваивание
//print(age); // Выведет 18
}Code language: JavaScript (javascript)
3 Запрет прямого обращения к свойствам и вызову методов у выражений с типом, допускающим null. Снова есть исключения: разрешены вызовы собственных методов и свойств null (hashCode, toString()).
void main() {
String? name; // Тип с поддержкой null, значение по умолчанию null
// Ошибка: прямой доступ к length вызовет сбой
// print(name.length);
// Корректно: разрешены встроенные методы null
print(name.toString()); // Выведет "null"
print(name.hashCode); // Выведет целое число
// Корректно: оператор безопасного доступа к нулю
print(name?.length); // Выведет null без ошибок
}Code language: PHP (php)
Значения по умолчанию
Переменные с поддержкой null, которым не присвоили значение вручную, по умолчанию равны null. Даже числовые переменные по умолчанию хранят null,
потому что в Dart числа, как и все остальные данные, являются объектами.
void main() {
int? lineCount;
assert(lineCount == null);
}Code language: JavaScript (javascript)
Примечание: проверка
assert()игнорируется в рабочем коде; при разработке если условие внутриassert()неверно, программа выбросит исключение
При включённой null safety переменные без поддержки null нужно инициализировать перед использованием:
int lineCount = 0;
Локальные переменные не обязательно инициализировать в той же строке, где объявлены, но значение должно быть присвоено до первого использования. Следующий код корректный, потому что Dart видит, что к моменту выполнения print() переменная lineCount гарантированно имеет не нулевое значение:
int lineCount;
if (weLikeToCount) {
lineCount = countLines();
} else {
lineCount = 0;
}
print(lineCount);
Code language: Dart (dart)
Обратите внимание: строки lineCount = countLines(); и lineCount = 0; — это присваивание значения переменной, а не её использование. Использование означает чтение хранимого значения. Например, следующий код вызовет ошибку:
void main() {
int lineCount;
print(lineCount);
}
Code language: Dart (dart)
Ошибка компиляции

Глобальные переменные и члены классов используют отложенную инициализацию: присваивание выполняется только при первом обращении к переменной.
Модификатор late для переменных
Модификатор late имеет два сценария применения:
- Объявление переменных без поддержки null с последующим присваиванием значения;
- Реализация отложенной инициализации переменных.
В большинстве случаев анализ потока кода Dart определяет, что переменная без поддержки null получила корректное значение перед использованием. Но в отдельных ситуациях анализ не работает — чаще всего это глобальные и экземплярные переменные: компилятор не может проверить, инициализированы ли они, поэтому выдаёт ошибку.
Если вы уверены, что переменная получит значение до обращения к ней, но компилятор этого не видит, используйте модификатор late для устранения ошибки:
В примере ниже description — глобальная переменная, компилятор не может понять, будет ли ей присвоено значение, но если вы на 100% уверены в этом, добавьте late:
late String description;
void main() {
description = 'Feijoada!';
print(description);
}
Code language: Dart (dart)
Предупреждение
Если объявить переменную с модификатором
lateи никогда не присвоить ей значение, при попытке обратиться к ней возникнёт исключение во время выполнения.
Если при объявлении late переменной сразу задать начальное значение, код инициализации выполнится только при первом обращении к переменной. Отложенная инициализация полезна в двух случаях:
- Переменная может никогда не использоваться, а её инициализация требует больших вычислительных ресурсов;
- При инициализации экземплярной переменной логика требует доступа к
this.
В примере ниже если переменная temperature никогда не будет использоваться, ресурсоёмкая функция readThermometer() не выполнится ни разу:
// Функция readThermometer() вызовется только при первом чтении temperature
late String temperature = readThermometer(); // Отложенная инициализация
Code language: JavaScript (javascript)
final и const
Если не хотите, чтобы значение переменной изменялось, используйте final или const; их можно использовать отдельно или вместе с указанием типа вместо var.
- Переменные
finalдопускают только одно присваивание; - Переменные
const— константы времени компиляции (у них неявно есть поведениеfinal).
Примечание
Члены экземпляра можно помечать модификатором
final, но неconst; константы на уровне класса объявляйте какstatic const.
Пример объявления переменных final:
final name = 'Jack'; // Без указания типа
final String nickname = 'Jason';
Code language: PHP (php)
Изменить значение final переменной нельзя, компилятор сразу выдаст ошибку:
void main() {
final name = 'Jack'; // Без указания типа
final String nickname = 'Jason';
name = 'Alice'; // Ошибка: переменная final получает значение только один раз
}Code language: JavaScript (javascript)
C:\dartdemo\firstdart>dart run
Building package executable...
Failed to build firstdart:firstdart:
bin/firstdart.dart:6:2: Error: Can't assign to the final variable 'name'.
name = 'Alice'; // Ошибка: переменная final получает значение только один разCode language: PHP (php)
const используется для создания констант времени компиляции. Если константа объявлена внутри класса, добавьте модификатор static — получится static const. При объявлении переменной const присваиваемое значение должно быть известно на этапе компиляции: числа, строковые литералы, другие константы const или результаты арифметических операций с константами:
const bar = 1000000; // Единица давления (дин/см²)
const double atm = 1.01325 * bar; // Стандартное атмосферное давление
Code language: JavaScript (javascript)
Ключевое слово const нужно не только для объявления констант-переменных, с его помощью создают константные объекты и конструкторы, возвращающие константные экземпляры. Любая переменная может принять константный объект как значение.
var foo = const [];
final bar = const [];
const baz = []; // Эквивалентно const []
Code language: PHP (php)
В выражениях присваивания для const переменных ключевое слово const можно опускать, как в примере с baz выше.
Даже если переменная хранит константный объект, если она не помечена как final или const, её ссылку можно заменить:
foo = [1, 2, 3]; // Изначально foo указывала на пустой константный массив, теперь ссылка изменена
Code language: JavaScript (javascript)
Но переменные const не допускают повторного присваивания, компилятор выдаст ошибку:
// Ошибка статического анализа
baz = [42]; // Ошибка: константные переменные не допускают повторное присваивание
Code language: JavaScript (javascript)
При объявлении констант допустимы проверка типов, преобразование типов (is, as), условные if внутри коллекций, операторы развёртки (..., ...?):
void main() {
const Object i = 3; // i — константа типа Object с целым значением
const list = [i as int]; // Использование преобразования типа
const map = {if (i is int) i: 'int'}; // Проверка is + if в коллекции
const set = {if (list is List<int>) ...list}; // Комбинация с оператором развёртки
}Code language: JavaScript (javascript)
Примечание
Ссылку на объект с модификатором
finalизменить нельзя, но внутренние поля объекта допускают изменение; напротив, объектconstи все его внутренние данные полностью неизменяемы.
Подробнее о создании константных коллекций через const смотрите документацию по спискам, словарям и классам.
* Переменная-подстановочный знак
Примечание по версии: переменные-подстановочные знаки требуют Dart версии 3.7 и выше.
Переменная с именем _ — несвязанная локальная переменная/параметр, выступающая лишь как заполнитель. Если есть выражение инициализации, оно выполнится, но прочитать значение этой переменной нельзя. В одной области видимости можно объявить несколько переменных с именем _ без конфликтов имён.
Что такое переменная-подстановочный знак
В Dart одиночное нижнее подчёркивание _ — это подстановочная переменная:
- Используется для приёма значений, которые не планируется использовать; сообщает компилятору «я не буду читать и использовать эту переменную»;
- Компилятор не выдаёт предупреждение «переменная объявлена, но не используется»;
- Читать переменную
_нельзя (вызовет ошибку), она только для отброса лишних данных.
// Берём только 1-е и 3-е значение, второе отбрасываем через _
final [a, _, c] = [10, 20, 30];
print(a); // 10
print(c); // 30
// print(_); // Ошибка, нельзя читать подстановочную переменнуюCode language: PHP (php)
Глобальные объявления и члены классов, отвечающие за приватность библиотеки, не допускают подстановочных переменных. Допустимы только внутри блочных областей видимости, примеры ниже:
- Объявление локальных переменных
void main() {
var _ = 1;
int _ = 2;
}
Code language: JavaScript (javascript)
- Переменная цикла for
for (var _ in list) {}
Code language: PHP (php)
- Параметр перехвата в catch
try {
throw '!';
} catch (_) {
print('oops');
}
Code language: PHP (php)
- Параметры обобщённых типов, обобщённые параметры функций
class T<_> {}
void genericFunction<_>() {}
takeGenericCallback(<_>() => true);
Code language: JavaScript (javascript)
- Параметры функций
Foo(_, this._, super._, void _()) {}
list.where((_) => true);
void f(void g(int _, bool _)) {}
typedef T = void Function(String _, String _);