Ответ
Эти три ключевых слова служат разным целям в системе типов Dart, и их часто путают.
| Ключевое слово | Статический тип | Изменение типа | Проверка типов | Основное назначение |
|---|---|---|---|---|
var |
Выводится при инициализации | Невозможно | На этапе компиляции | Укорочение записи для локальных переменных с очевидным типом. |
dynamic |
dynamic (специальный тип) |
Возможно | На этапе выполнения (отложена) | Работа с динамическим контентом (JSON, плагины), когда тип неизвестен на этапе компиляции. |
Object? |
Object? (базовый nullable-тип) |
Невозможно (но можно присвоить любой объект) | На этапе компиляции | Хранение любого объекта с обязательной проверкой или приведением типа перед использованием его специфичных методов. |
Детальное сравнение с примерами:
-
var— вывод типа:var message = 'Привет'; // Статический тип выведен как `String` // message = 123; // ОШИБКА компиляции: тип `int` не присваивается `String`. print(message.length); // OK, компилятор знает, что это String. -
dynamic— отключение статической проверки:dynamic item = 'Текст'; print(item.length); // OK, работает (item — String). item = 100; // Теперь item содержит `int`. print(item.length); // ОШИБКА ВО ВРЕМЯ ВЫПОЛНЕНИЯ (Runtime Error)! // Компилятор пропустит это, но при запуске у int нет свойства .length.dynamicследует использовать осознанно, только когда тип действительно неизвестен (например, данные изjson.decode()). -
Object?— тип верхнего уровня:Object? something = 'Строка'; something = 45; // OK, int — это тоже Object. something = null; // OK, Object? — nullable. // print(something.length); // ОШИБКА компиляции! // Компилятор не знает, что something — String, даже если там строка. // Требуется явная проверка или приведение типа: if (something is String) { print(something.length); // OK, в этой ветке тип продвинут до String. } // ИЛИ print((something as String).length); // Runtime error, если something не String.
Рекомендация по использованию:
- Предпочитайте
varдля локальных переменных, где тип ясен. - Используйте явные типы (
String,List<int>) для публичных API (полей классов, аргументов и возвращаемых значений методов) для лучшей документированности. Object?используйте, когда вам нужна коллекция или переменная, гарантированно способная хранить любой объект, но с последующей безопасной проверкой типа (is).dynamic— инструмент на крайний случай. Его использование должно быть ограничено сценариями, где статическая типизация невозможна.