Функции, стрелочный синтаксис и параметры
Функция — это переиспользуемый кусок логики; в Dart у неё гибкие параметры и компактная запись.
Суть: функции принимают параметры (позиционные, опциональные
[ ]или именованные{ }), возвращают значение и могут быть записаны коротко через стрелку=>.
Функции в Dart — это ещё и полноценные значения, которые можно передавать как аргументы. Когда вы пишете обработчик нажатия onPressed: () { ... }, вы передаёте функцию внутрь другой функции. Такие анонимные функции называют замыканиями: они запоминают переменные из окружающего кода. Эта идея — функция как параметр — пронизывает весь Flutter, ведь почти каждый интерактивный виджет принимает колбэк, который вызовет в нужный момент.
Без функций код превращается в одну длинную простыню, которую невозможно читать и переиспользовать. Функция упаковывает действие под именем: один раз описали — много раз вызвали. В Dart функция объявляется так: тип возвращаемого значения, имя, скобки с параметрами и тело в фигурных скобках.
int add(int a, int b) {
return a + b;
}
// то же самое короче — стрелочный синтаксис:
int addShort(int a, int b) => a + b;
void greet(String name) {
print('Привет, $name!');
}
Стрелка => — это сокращение для функций, тело которых состоит из одного выражения. => a + b означает { return a + b; }. В Flutter вы будете встречать стрелки на каждом шагу, особенно в обработчиках нажатий.
Как работают параметры под капотом
У Dart три вида параметров, и это его сильная сторона. Позиционные передаются по порядку. Опциональные позиционные оборачиваются в квадратные скобки [ ] и могут быть пропущены. Именованные оборачиваются в фигурные { } и передаются по имени — именно их использует почти каждый виджет Flutter.
void build(child, {color, padding})
| |
обязательный именованные (по имени, в любом порядке)
|
вызов: build(text, color: blue, padding: 8)
|
можно поменять местами: padding: 8, color: blue
// именованные параметры с значением по умолчанию и required
void createButton({
required String label, // обязателен, хоть и именованный
Color color = Colors.blue,
double width = 100,
}) {
// ...
}
createButton(label: 'OK'); // color и width — дефолтные
createButton(label: 'OK', color: Colors.red);
Ключевое слово required делает именованный параметр обязательным: компилятор не даст вызвать функцию без него. Это и есть причина, по которой код Flutter так читаем — у каждого аргумента есть подпись.
Запустим Python-аналог именованных параметров со значениями по умолчанию — логика идентична Dart:
# Аналог именованных параметров Dart с дефолтами и обязательным аргументом
def create_button(label, color='blue', width=100):
return f"Кнопка [{label}] цвет={color} ширина={width}"
print(create_button('OK')) # дефолты
print(create_button('Стоп', color='red')) # переопределили цвет
print(create_button('Шире', width=200, color='green')) # порядок любой
Частые ошибки
- Забыть
requiredу обязательного именованного параметра — тогда его можно не передать, и значение окажется null. - Путать
[ ]и{ }. Квадратные — опциональные позиционные, фигурные — именованные. Это разные механизмы. - Возвращать значение из
void-функции.voidозначает «ничего не возвращаю».
Best practices
- Для функций с двумя и более параметрами предпочитайте именованные — вызов становится самодокументируемым.
- Однострочные функции пишите через
=>— короче и чище. - Давайте функциям имена-глаголы:
calculateTotal,fetchUser, а неdata.
Ещё одна деталь, которая сэкономит вам часы отладки: порядок и обязательность параметров. Позиционные аргументы нельзя пропустить в середине — если второй опциональный нужен, придётся указать и первый. Именованные же свободны от этого ограничения, и потому виджеты Flutter с их десятком настроек используют именно их. Привыкайте читать сигнатуру функции как список возможностей: что обязательно, что имеет умолчание, а что можно опустить.
Итог: функции — это кирпичики логики. Освойте именованные параметры с required и значениями по умолчанию — на них держится весь API Flutter, и без них код виджетов покажется набором случайных скобок.