Dart за полчаса
что надо знать, чтобы читать
Что это
Dart похож одновременно на Java, JavaScript и TypeScript. Если ты прочитал
главу 9, половина уже знакома: типы, async/await, классы.
В статье — то, что отличается и встречается в каждом файле Flutter-проекта.
Как выглядит в коде
class City {
final String name;
final double? temp;
const City({required this.name, this.temp});
String get report => temp == null
? '$name: нет данных'
: '$name: ${temp! > 0 ? '+' : ''}$temp°';
}
void main() {
final cities = <City>[
const City(name: 'Oslo', temp: 4),
const City(name: 'Tromsø'),
];
for (final c in cities) {
print(c.report);
}
}Что здесь важно
final вместо const и let. final — присвоить один раз. const —
значение известно на этапе компиляции. Во Flutter const встречается
постоянно: он позволяет не пересоздавать виджеты при перерисовке.
double? temp — тип с вопросом, то же, что number | null в TypeScript.
Dart строг к пустоте так же, как TypeScript со strict: обратиться к temp
напрямую нельзя, пока не проверил.
temp! — утверждение «тут точно не пусто». Прямой аналог as из статьи
9.5 и такой же источник проблем: это обещание компилятору, а не проверка.
Если ошибся, приложение упадёт с Null check operator used on a null value.
required — обязательный именованный параметр. Без него аргумент можно
не передать.
$name и ${выражение} — подстановка в строку, как f-строки в Python.
get report => ... — вычисляемое свойство: обращаются как к полю, без
скобок.
Именованные параметры
Главное синтаксическое отличие, к которому надо привыкнуть:
City(name: 'Oslo', temp: 4) // именованные, в фигурных скобкахВо Flutter почти все параметры именованные, и это объясняет, почему код выглядит таким многословным:
Padding(
padding: const EdgeInsets.all(16),
child: Text('Привет'),
)Плюс в том, что при чтении всегда видно, что означает каждое значение.
Остальное коротко
| Запись | Что значит |
|---|---|
late | «значение будет, но позже» — обещание, проверяется при работе |
?. | безопасный доступ, как в JS (статья 9.1) |
?? | значение по умолчанию |
.. | каскад: несколько операций с одним объектом |
=> | короткая форма функции из одного выражения |
List<City> | список городов; <> — как дженерики (статья 9.4) |
late стоит упомянуть отдельно. Это способ сказать «я присвою это
позже». Если не присвоил, а обратился — ошибка во время работы. ИИ
использует late, чтобы обойти требование инициализации, — и это та же
заглушка, что as и !.
Как сказать ИИ
Объясни этот класс построчно: что значит final, что
required, что делает знак восклицания после temp.Здесь используется `late` и `!`. Перепиши без них,
через нормальные проверки на null. Если где-то без них
не обойтись — объясни почему, а не переписывай.Напиши модель данных для ответа API: вот пример JSON.
Поля, которых может не быть, делай nullable честно.
Добавь фабрику fromJson с проверками, а не приведением типов.На что смотреть
! на каждом шагу. Приложение будет падать там, где данных не оказалось.
late вместо нормальной инициализации. Та же проблема, только позже.
Код для старых версий Flutter. Устаревшие имена виджетов и параметров.
dynamic. Полный аналог any из TypeScript: отключает проверку.
Разбор JSON без проверок. json['main']['temp'] as double падает, если
сервер ответил ошибкой, — ровно так же, как в статьях 2.12 и 9.5.
Шпаргалка
final— присвоить один раз,const— известно при компиляции.double?— может быть пустым; Dart не даст обратиться без проверки.!,lateи приведение типа отключают проверку пустоты.Параметры во Flutter почти всегда именованные:
City(name: ..., temp: ...).$nameи${выражение}— подстановка в строку.dynamic— этоany, со всеми последствиями.