Для чего используется ключевое слово `var` в Dart и в чем его отличие от `dynamic` и `final`?

«Для чего используется ключевое слово `var` в Dart и в чем его отличие от `dynamic` и `final`?» — вопрос из категории Dart Core, который задают на 52% собеседований Flutter Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Ключевое слово var в Dart используется для объявления переменной с автоматическим выводом типа (type inference). Тип переменной определяется компилятором на основе значения, присвоенного при инициализации, и после этого фиксируется.

Основные правила и отличия:

Ключевое слово Определение типа Изменяемость Повторное присваивание
var Выводится при инициализации, затем фиксирован. Да (но тип менять нельзя). Да, значением того же типа.
dynamic Не проверяется на этапе компиляции. Да. Да, значением ЛЮБОГО типа.
final Выводится или задается явно, затем фиксирован. Нет (переменная только для чтения). Нет, только одно присваивание.
const Выводится или задается явно, значение известно на этапе компиляции. Нет. Нет.

Практические примеры:

// VAR: тип выводится как String
var name = 'Alice'; // Тип: String
name = 'Bob';       // OK
// name = 42;       // ОШИБКА компиляции: тип int не может быть присвоен переменной типа String

// DYNAMIC: отключает проверку типов на этапе компиляции
dynamic data = 'Hello';
data = 100;          // OK, тип изменен с String на int
data = [];           // OK, тип изменен на List
// Ошибки типа обнаруживаются только во время выполнения (Runtime Error).

// FINAL: переменная только для чтения
final apiKey = 'abc123'; // Тип выведен как String
// apiKey = 'xyz';       // ОШИБКА компиляции: final переменную нельзя изменить.
final List<int> numbers = [1, 2, 3];
numbers.add(4);          // OK, содержимое mutable-коллекции можно менять.
// numbers = [5, 6];     // ОШИБКА: нельзя присвоить новый объект.

// CONST: константа времени компиляции
const maxItems = 10; // Значение должно быть известно при компиляции.
const defaultPadding = EdgeInsets.all(8.0);

Рекомендация по использованию в Flutter:

  • Используйте var, когда тип значения очевиден из контекста (var controller = TextEditingController()).
  • Избегайте dynamic без крайней необходимости (например, при работе с JSON до десериализации в модель).
  • Широко используйте final для переменных, которые не должны переназначаться — это делает код безопаснее и понятнее.