В Dart функции также являются объектами — это отличает его от других языков программирования.
Функции — объекты первого класса
Dart — полностью объектно-ориентированный язык: сами функции являются объектами с типом Function.
Их можно присваивать переменным и передавать как аргументы другим функциям;
Экземпляры классов можно вызывать напрямую как функции
1 Стандартное объявление функции
// Полное объявление с аннотациями типа возвращаемого значения и параметров
bool isNoble(int atomicNumber) {
return _nobleGases[atomicNumber] != null;
}Code language: JavaScript (javascript)
Полный пример
// Таблица соответствия атомных номеров благородных газов
final Map<int, String> _nobleGases = {
2: 'He',
10: 'Ne',
18: 'Ar',
36: 'Kr',
54: 'Xe',
86: 'Rn',
};
// Полное объявление с типом возврата и типами параметров
// Тип int не поддерживает null; используйте int? для необязательных параметров
bool isNoble(int? atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
void main() {
print(isNoble(null)); // null не является ключом карты → false
print(isNoble(2)); // Соответствует благородному газу → true
print(isNoble(9)); // Совпадений нет → false
print(isNoble(86)); // Соответствует благородному газу → true
}Code language: PHP (php)
false
true
false
trueCode language: JavaScript (javascript)
2 Пропуск аннотаций типов
Руководство по стилю Effective Dart предписывает использовать полные явные аннотации типов для публичных внешних API.
Для внутренних приватных функций аннотации типов можно опускать
Пример
final Map<int, String> _nobleGases = {
2: 'He',
10: 'Ne',
18: 'Ar',
36: 'Kr',
54: 'Xe',
86: 'Rn',
};
isNoble(atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
void main() {
print(isNoble(null)); // null не является ключом карты → false
print(isNoble(2)); // Соответствует благородному газу → true
print(isNoble(9)); // Совпадений нет → false
print(isNoble(86)); // Соответствует благородному газу → true
}
Code language: PHP (php)
В примере выше функция isNoble не указывает возвращаемый тип bool и тип параметра int?, но работает корректно.
Если типы не указаны, Dart выполняет автоматический вывод типов:
- Параметр
atomicNumber: без явного типа → выводится какdynamic(динамический тип, принимает любые значения: числа, строки, null) - Возвращаемое значение: без аннотации типа в начале → Dart определяет возвращаемый тип как
boolпо выражению послеreturn, без записи в коде
Почему публичные API обязательно должны иметь явные типы?
Читаемость: разработчики, вызывающие вашу функцию, сразу видят типы входных и выходных данных, не читая внутренний код для догадок;
Безопасность типов: тип dynamic отключает статическую проверку; передача неверных типов не вызовет ошибку компиляции и часто приводит к падениям во время выполнения;
Подсказки IDE: аннотации типов активируют автодополнение и подсказки по параметрам в редакторе; без типов IDE не может показать точные предложения.
Когда можно опускать аннотации типов?
Рекомендуется только для локального приватного кода: функций, используемых исключительно внутри текущего файла и никогда не вызываемых снаружи.
Сокращенная стрелковая синтаксическая запись (=>)
Если тело функции (код в фигурных скобках {}) содержит только одно возвращающее выражение, можно использовать стрелковую запись.
Пример
bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;Code language: PHP (php)
=> exprэквивалентно{ return expr; };- Между стрелкой и точкой с запятой можно писать только выражения; операторы как
ifзапрещены (используйте тернарный оператор).
// Таблица соответствия атомных номеров благородных газов
final Map<int, String> _nobleGases = {
2: 'Гелий',
10: 'Неон',
18: 'Аргон',
36: 'Криптон',
54: 'Ксенон',
86: 'Радон',
};
// Сокращенная стрелковая функция: возвращает выражение сразу в одну строку, эквивалентна блочной функции с return
bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;
void main() {
// Проверка существующих благородных газов
print(isNoble(2)); // true
print(isNoble(18)); // true
// Проверка обычных элементов
print(isNoble(6)); // false (Углерод)
print(isNoble(99)); // false (соответствующего элемента нет)
}Code language: PHP (php)

Параметры
Функции поддерживают обязательные позиционные параметры, после которых выбирается один из двух вариантов: именные параметры или опциональные позиционные параметры — их нельзя смешивать.
При объявлении или вызове параметров разрешена запятая в конце строки , для улучшения читаемости кода.
1. Именные параметры Named parameters
Ограничены фигурными скобками {}, по умолчанию необязательные; добавьте required для принудительной передачи.
1) Простые необязательные именные параметры (без значения по умолчанию, значение по умолчанию — null, тип помечается знаком ?)
void enableFlags({bool? bold, bool? hidden}) {}
// При вызове явно указывайте имена параметров
enableFlags(bold: true, hidden: false);
Code language: JavaScript (javascript)
Полный пример
/// Включить флаги стиля текста: жирный, скрытый
void enableFlags({bool? bold, bool? hidden}) {
print('Жирный: $bold, Скрытый: $hidden');
}
void main() {
// Передать все именные параметры
enableFlags(bold: true, hidden: false);
// Передать только один именной параметр, второй будет null
enableFlags(bold: true);
// Передать только hidden
enableFlags(hidden: true);
// Не передавать никаких параметров, оба значения равны null
enableFlags();
}Code language: JavaScript (javascript)
Результат выполнения
D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
Жирный: true, Скрытый: false
Жирный: true, Скрытый: null
Жирный: null, Скрытый: true
Жирный: null, Скрытый: nullCode language: JavaScript (javascript)
2) Установка константных значений по умолчанию на этапе компиляции (не требуется знак ?, так как есть значение по умолчанию)
void enableFlags({bool bold = false, bool hidden = false}) {}
enableFlags(bold: true); // hidden автоматически принимает false
Code language: JavaScript (javascript)
Пример
/// Включить флаги стиля текста: жирный, скрытый
void enableFlags({bool bold = false, bool hidden = false}) {
print('Жирный: $bold, Скрытый: $hidden');
}
void main() {
enableFlags();//Параметры не переданы, оба используют значение по умолчанию false → Жирный: false, Скрытый: false
}Code language: JavaScript (javascript)
3) Обязательные именные параметры с required (Примечание: широко используются в конструкторах компонентов Flutter. Пример ниже — код Flutter, подробнее смотрите в туториалах Flutter.)
const Scrollbar({super.key, required Widget child});
// Параметры required также поддерживают необязательные типы
const Scrollbar({super.key, required Widget? child});
Code language: JavaScript (javascript)
Dart не требует размещать именные параметры в конце списка; их можно вставлять в любое место списка параметров
repeat(times: 2, () {})Code language: CSS (css)
2. Опциональные позиционные параметры Optional positional parameters
Ограничены квадратными скобками [], при пропуске принимают значение null; можно задать константные значения по умолчанию.
// Без значения по умолчанию, тип помечен знаком ?
String say(String from, String msg, [String? device]) {
var result = '$from says $msg';
if (device != null) result = '$result with a $device';
return result;
}
assert(say('Bob', 'Howdy') == 'Bob says Howdy');
assert(say('Bob', 'Howdy', 'smoke signal') == 'Bob says Howdy with a smoke signal');
Code language: PHP (php)
Полный пример
// [String? device] опциональный позиционный параметр без значения по умолчанию, равен null при пропуске
String say(String from, String msg, [String? device]) {
var result = '$from says $msg';
if (device != null) {
result = '$result with a $device'; //Добавить информацию об устройстве к строке, если device не равен null
}
return result;
}
void main() {
// Пропустить третий опциональный параметр
String res1 = say('Bob', 'Howdy');
print(res1);
// Передать третий опциональный позиционный параметр
String res2 = say('Bob', 'Howdy', 'smoke signal');
print(res2);
// Вручную передать null опциональному параметру
String res3 = say('Alice', 'Hi', null);
print(res3);
}Code language: JavaScript (javascript)
Задание значений по умолчанию:
String say(String from, String msg, [String device = 'carrier pigeon']) {
return '$from says $msg with a $device';
}
assert(say('Bob', 'Howdy') == 'Bob says Howdy with a carrier pigeon');
Code language: PHP (php)
Полный пример
// Опциональный позиционный параметр со значением по умолчанию carrier pigeon (почтовый голубь)
String say(String from, String msg, [String device = 'carrier pigeon']) {
return '$from says $msg with a $device';
}
void main() {
// Пропустить третий опциональный параметр, автоматически используется значение по умолчанию carrier pigeon
String res1 = say('Bob', 'Howdy');
print(res1); //Bob says Howdy with a carrier pigeon
// Передать пользовательское устройство для переопределения значения по умолчанию
String res2 = say('Bob', 'Howdy', 'smoke signal');
print(res2); //Bob says Howdy with a smoke signal
String res3 = say('Alice', 'Hello', 'mobile phone');
print(res3); // Alice says Hello with a mobile phone
String res4 = say('Jack', 'Tom', 'website foxdevelop.com');
print(res4); // Jack says Tom with a website foxdevelop.com
}Code language: JavaScript (javascript)
Результат выполнения
Built firstdart:firstdart.
Bob says Howdy with a carrier pigeon
Bob says Howdy with a smoke signal
Alice says Hello with a mobile phone
Jack says Tom with a website foxdevelop.comCode language: JavaScript (javascript)
Входная функция main ()
Любая программа Dart должна содержать верхнеуровневую функцию main() — это единственная точка входа в программу.
- Базовая версия без параметров
void main() {
print('Hello, welcome to foxdevelop.com!');
}
Code language: JavaScript (javascript)
Hello, welcome to foxdevelop.com!Code language: CSS (css)
- Консольная программа с аргументами запуска
// Команда запуска: dart run firstdart.dart 1 test
void main(List<String> arguments) {
print(arguments); // [1, test]
}
Code language: JavaScript (javascript)
Для разбора сложных консольных аргументов используйте официальную библиотеку args.
Замените firstdart.dart выше на имя вашего Dart-файла

Функции как объекты первого класса First-class objects
1 Передача функций как параметров
void printElement(int element) => print(element);
var list = [1, 2, 3];
list.forEach(printElement); // Передать функцию напрямую
Code language: PHP (php)
Полный пример
void main() {
void printElement(int element) => print(element);
var list = [1, 2, 3];
list.forEach(printElement); // Передать функцию напрямую
}Code language: PHP (php)
Вывод
1
2
3
2 Присвоение анонимных функций переменным
void main() {
var loudify = (msg) => '!!! ${msg.toUpperCase()} !!!';
print(loudify('hello')); //!!! HELLO !!!
}Code language: JavaScript (javascript)
Типы функций Function Type
Можно явно объявлять типы переменных-функций
Формат: ТипВозврата Function(СписокПараметров, {ИменныеПараметры})
void greet(String name, {String greeting = 'Hello'}) => print('$greeting $name!');
// Объявить переменную функционального типа
void Function(String, {String greeting}) g = greet;
g('Dash', greeting: 'Howdy');
Code language: JavaScript (javascript)
С помощью typedef создавайте псевдонимы функциональных типов для повышения переиспользуемости и читаемости.
{String greeting}) → один именной параметр greeting типа String
void main() {
void greet(String name, {String greeting = 'Hello'}) => print('$greeting $name!');
// Объявить переменную функционального типа
void Function(String, {String greeting}) g = greet;
g('Jack', greeting: 'Howdy');
}Code language: JavaScript (javascript)
Вывод
Howdy Jack!
Анонимные функции (Лямбда / Замыкание Closure)
Функции без собственного имени, два варианта записи:
- Блочная запись (многострочная)
void main() {
const list = ['apples', 'bananas'];
var uppercaseList = list.map((item) {
return item.toUpperCase();
}).toList();
print(uppercaseList);
}Code language: PHP (php)
(item) { return item.toUpperCase(); } в коде выше — это анонимная функция (лямбда)
Вывод: [APPLES, BANANAS]
- Сокращенная стрелковая запись (однострочное выражение)
void main() {
const list = ['fox', 'develop','foxdevelop.com'];
var uppercaseList = list.map((item) => item.toUpperCase()).toList();
uppercaseList.forEach((item) => print('$item: ${item.length}'));
}
Code language: PHP (php)
Вывод
FOX: 3
DEVELOP: 7
FOXDEVELOP.COM: 14Code language: HTTP (http)
Лексическая область видимости Lexical scope
Dart использует статическую лексическую область видимости: область переменной определяется иерархией фигурных скобок кода, внутренние области имеют доступ ко всем переменным внешних областей.
bool topLevel = true;
void main() {
var insideMain = true;
void myFunction() {
var insideFunction = true;
void nestedFunction() {
var insideNestedFunction = true;
// Все доступны
assert(topLevel && insideMain && insideFunction && insideNestedFunction);
}
}
}
Code language: JavaScript (javascript)
Лексические замыкания Lexical closures
Замыкание: объект функции может захватывать и хранить переменные внешней области видимости и обращаться к ним даже после выхода из исходной области.
Function makeAdder(int addBy) {
// Захват внешней переменной addBy
return (int i) => addBy + i;
}
void main() {
var add2 = makeAdder(2);
var add4 = makeAdder(4);
assert(add2(3) == 5);
assert(add4(3) == 7);
}
Code language: PHP (php)
Пошаговый разбор выполнения вышеприведенного кода
Шаг 1: var add2 = makeAdder(2);
- Вызвать
makeAdder, передатьaddBy = 2 - Создать анонимную функцию:
(int i) => 2 + i - Присвоить эту функцию переменной
add2. С этого момента add2 — объект функции с телом(int i) => 2 + i; он принимает целое число i и возвращает i+2 - Выполнение функции
makeAdderзавершается, но анонимная функция навсегда запоминаетaddBy=2
Шаг 2: var add4 = makeAdder(4);
- Повторно вызвать
makeAdder, передатьaddBy = 4 - Создать совершенно новую независимую анонимную функцию:
(int i) => 4 + i - Присвоить
add4, которая хранит свою независимую копиюaddBy=4без влияния на add2. То есть значение addBy хранится отдельно в двух объектах-функциях add2 и add4, один хранит 2, другой — 4
- Вызов
makeAdder(2)создает независимое замыкание с единственным привязанным значениемaddBy = 2, присвоенноеadd2; - Вызов
makeAdder(4)создает совершенно новое отдельное замыкание с единственным привязанным значениемaddBy = 4, присвоенноеadd4; add2иadd4— полностью независимые объекты-функции, каждый хранит в закрытом виде захваченную переменнуюaddByбез взаимного влияния.
Шаг 3: Вызвать add2(3)
Выполнить внутреннюю функцию: 2 + 3 = 5, утверждение выполняется
Шаг 4: Вызвать add4(3)
Выполнить внутреннюю функцию: 4 + 3 = 7, утверждение выполняется
Функциональные Tear-offs
Если вызывать функцию / метод без скобок, создается tear-off (легковесное замыкание), заменяющее рукописные анонимные лямбды и упрощающее код.
Это рекомендуемая запись: достаточно передать функцию напрямую.
var charCodes = [68, 97, 114, 116];
var buffer = StringBuffer();
charCodes.forEach(print); // Функциональный tear-off
charCodes.forEach(buffer.write); // Методный tear-off
Code language: PHP (php)
Длинная эквивалентная запись
charCodes.forEach((code) => print(code));
charCodes.forEach((code) => buffer.write(code));
Code language: PHP (php)
Проверка равенства функций
- Верхнеуровневые функции, статические методы: оператор
==возвращает true при полном совпадении имен функций; - Методы экземпляров: только tear-offs, привязанные к одному и тому же экземпляру объекта, считаются равными.
void foo() {}
class A {
static void bar() {}
void baz() {}
}
void main() {
var x = foo;
assert(foo == x);
x = A.bar;
assert(A.bar == x);
var v = A(), w = A(), y = w;
x = w.baz;
assert(y.baz == x); // Один экземпляр → равны
assert(v.baz != w.baz); // Разные экземпляры → не равны
}
Code language: JavaScript (javascript)
Возвращаемые значения Return values
- Любая функция имеет возвращаемое значение: если явного
returnнет, в конец кода неявно добавляетсяreturn null;
foo() {}
assert(foo() == null);
Code language: JavaScript (javascript)
- Возврат нескольких значений: использовать кортежи Record
(String, int) foo() {
return ('something', 42);
}
Code language: JavaScript (javascript)
Аксессоры Getter & Setter
Чтение или присваивание любого свойства по сути вызывает соответствующий getter или setter; обычные переменные автоматически создают неявные аксессоры, их также можно явно описать вручную.
Преимущество: внешний код обращается единообразно через .ИмяСвойства, внутреннюю логику можно изменять в любое время без исправления вызывающего внешнего кода.
String _secret = 'Hello';
// Getter для чтения
String get secret {
print('Вызван getter');
return _secret.toUpperCase();
}
// Setter для присваивания
set secret(String newMsg) {
print('Вызван setter');
if (newMsg.isNotEmpty) _secret = newMsg;
}
void main() {
print(secret); // Чтение, активирует getter → HELLO
secret = 'Dart is fun'; // Присвоение, активирует setter
print(secret); // DART IS FUN
}
Code language: JavaScript (javascript)
* Генераторы Generators
Лениво создают последовательности по запросу, два вида: синхронные и асинхронные, используют yield для выдачи значений.
- Синхронный генератор
sync*, возвращаетIterable
Iterable<int> naturalsTo(int n) sync* {
int k = 0;
while (k < n) yield k++;
}
Code language: HTML, XML (xml)
- Асинхронный генератор
async*, возвращаетStream
Stream<int> asyncNaturalsTo(int n) async* {
int k = 0;
while (k < n) yield k++;
}
Code language: JavaScript (javascript)
- Оптимизация рекурсивных генераторов
yield*(делегирует другому генератору для повышения производительности)
Iterable<int> naturalsDownFrom(int n) sync* {
if (n > 0) {
yield n;
yield* naturalsDownFrom(n - 1);
}
}
Code language: HTML, XML (xml)