В чём разница между final и const в Dart?
final: ссылка присваивается один раз в рантайме, объект может быть мутабелен. const: значение известно на этапе компиляции, объект полностью иммутабелен и переиспользуется (canonicalized). В Flutter const виджеты не пересоздаются при rebuild.
final: присваивается один раз в рантайме
final переменная может быть инициализирована любым выражением, которое вычисляется в рантайме, но присваивается ровно один раз — после этого ссылку изменить нельзя. Объект, на который она ссылается, может быть мутабельным.
void main() {
final now = DateTime.now(); // вычисляется в рантайме
final list = [1, 2, 3]; // ссылка неизменна, но список мутабелен
list.add(4); // OK — меняем содержимое
// list = []; // Compile error — нельзя переназначить
print(now); // текущее время
print(list); // [1, 2, 3, 4]
}
const: вычисляется на этапе компиляции
const требует, чтобы значение было известно на этапе компиляции. Это compile-time constant: значение встраивается в бинарник, объект разделяется между всеми использованиями (canonicalized), и он полностью иммутабелен.
void main() {
const pi = 3.14159;
const greeting = 'Hello, Dart!';
const size = Size(100, 200); // Size должен быть const-конструктором
// const list = [DateTime.now()]; // Compile error — DateTime.now() не compile-time
const a = [1, 2, 3];
const b = [1, 2, 3];
print(identical(a, b)); // true — один объект в памяти
// a.add(4); // Unsupported operation: Cannot add to an unmodifiable list
}
Ключевые различия
| final | const | |
|---|---|---|
| Когда вычисляется | Рантайм | Компиляция |
| Мутабельность объекта | Объект может быть мутабелен | Объект полностью иммутабелен |
| Sharing | Каждый раз новый объект | Один объект для одинаковых значений |
| Где использовать | Поля класса, локальные переменные | Магические числа, виджеты Flutter |
const в Flutter — оптимизация перерисовки
Во Flutter const виджеты создаются один раз и не пересоздаются при setState. Это главная причина, почему линтер (prefer_const_constructors) агрессивно предлагает добавить const.
class MyWidget extends StatelessWidget {
const MyWidget({super.key}); // const конструктор
@override
Widget build(BuildContext context) {
return Column(
children: [
const Text('Static label'), // пересоздаваться не будет
Text(DateTime.now().toString()), // пересоздаётся при rebuild
const Padding(
padding: EdgeInsets.all(16), // EdgeInsets.all(16) — compile-time const
child: Icon(Icons.star),
),
],
);
}
}
const конструктор и поля
Чтобы класс имел const конструктор, все его поля должны быть final и инициализироваться только compile-time константами.
class Point {
final double x;
final double y;
const Point(this.x, this.y);
double get distanceFromOrigin => (x * x + y * y).sqrt();
// Оператор может быть вычислен, но не является const
}
void main() {
const origin = Point(0, 0);
const p1 = Point(3, 4);
const p2 = Point(3, 4);
print(identical(p1, p2)); // true — один объект
}
Подводные камни
- final не защищает содержимое:
final list = []— ссылку изменить нельзя, ноlist.add()работает. Для иммутабельного списка нуженconstилиList.unmodifiable(). - const объект нельзя изменить даже через методы:
const [1,2,3].add(4)выброситUnsupportedErrorв рантайме — не compile error. - Забытый const в Flutter: если виджет можно сделать const, но не сделали — Flutter пересоздаёт его при каждом rebuild без нужды. Линтер
flutter analyzeэто поймает. - const и late несовместимы:
late const— синтаксическая ошибка, потому чтоlateпо определению инициализируется в рантайме. - Canonicalization только для одинаковых значений:
const Point(1, 2)иconst Point(1, 3)— разные объекты. Sharing работает только при полном совпадении. - const в разных пакетах: compile-time const не переживает hot reload при изменении значения в другом пакете — нужен полный restart.
Common mistakes
- Сводить «
finalиconstв Dart» к синтаксису и не объяснять isolate. - Игнорировать жизненный цикл, основной поток или момент освобождения ресурсов в сценарии dart-3.
- Выбирать API по привычке, не проверяя состояние, ошибки, доступность и платформенные ограничения.
What the interviewer is testing
- Формулирует точную модель для «
finalиconstв Dart» и подтверждает ее корректным примером. - Умеет связать ответ с null safety, тестированием и отладкой на устройстве.
- Называет ограничения подхода dart-3, включая производительность, память и сопровождение.