В чем разница между final и const в Dart?

«В чем разница между final и const в Dart?» — вопрос из категории Dart Core, который задают на 29% собеседований Flutter Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Ключевые слова final и const используются для объявления неизменяемых переменных, но их семантика и область применения различаются.

final (финальная переменная)

  • Значение присваивается один раз в момент выполнения (runtime).
  • Инициализацию можно отложить, например, выполнить в конструкторе.
  • Объект, на который ссылается final переменная, может быть изменяемым (mutable).

const (константа времени компиляции)

  • Значение должно быть известно на этапе компиляции.
  • Это не просто константа, а канонизированный объект. Создавая одинаковые const-объекты, вы получаете ссылку на один и тот же экземпляр в памяти.
  • Сам объект и все его поля (если это коллекция или объект) должны быть неизменяемыми (immutable).

Сравнение на примерах:

// FINAL: Значение вычисляется в runtime.
final currentTime = DateTime.now(); // OK
final List<int> myList = [1, 2, 3];
myList.add(4); // OK! Список изменяем, хотя ссылка `myList` - нет.

// CONST: Значение должно быть известно при компиляции.
const maxItems = 100; // OK, литерал.
// const currentTimeConst = DateTime.now(); // ОШИБКА: runtime-значение.

const List<int> constList = [1, 2, 3];
// constList.add(4); // ОШИБКА времени компиляции: список неизменяем.

// Канонизация:
const a = const Point(1, 1); // Ключевое слово 'const' можно опустить: const a = Point(1, 1);
const b = Point(1, 1);
print(identical(a, b)); // true. Это один и тот же объект в памяти.

Использование в Flutter: const активно применяется для создания виджетов, так как это даёт оптимизацию производительности — фреймворк не перестраивает const-виджеты, а повторно использует их.

@override
Widget build(BuildContext context) {
  return const Text( // Хорошая практика для статического текста
    'Hello, World!',
    style: TextStyle(fontSize: 16),
  );
}