Паттерны и сопоставление (3.0)
Часть раздела Объектно-ориентированное программирование путешествия по Dart на Coddy. Урок 87 из 110.
В Dart 3 появилось сопоставление с образцами — мощный способ выполнять destructuring и проверять data в одном выражении expression. Образцы позволяют извлекать значения из объектов, проверять их структуру и связывать переменные — всё одновременно.
Вы уже видели базовую деструктуризацию с записями. Шаблоны расширяют её, позволяя работать с объектами, списками и отображениями:
void main() {
// Паттерны списков
var numbers = [1, 2, 3];
var [a, b, c] = numbers;
print('$a, $b, $c'); // 1, 2, 3
// Паттерны Map
var user = {'name': 'Alice', 'age': 30};
var {'name': name, 'age': age} = user;
print('$name is $age'); // Alice is 30
}Шаблоны становятся особенно мощными в выражениях switch. Вы можете одновременно сопоставлять тип, значение и структуру:
String describe(Object obj) {
return switch (obj) {
int n when n < 0 => 'Negative number',
int n => 'Positive number: $n',
String s => 'String of length ${s.length}',
[int first, ...] => 'List starting with $first',
_ => 'Something else',
};
}
void main() {
print(describe(-5)); // Отрицательное число
print(describe(42)); // Положительное число: 42
print(describe([1, 2, 3])); // List starting with 1
}Конструкция when добавляет условия к шаблонам, а ... сопоставляет оставшиеся elements в списке. Подчёркивание _ действует как подстановочный символ, который сопоставляется с чем угодно. В сочетании с запечатанными классами шаблоны обеспечивают исчерпывающую и типобезопасную обработку сложных структур данных.
Задание
ЛегкоДавайте создадим classifier, который использует сопоставление с шаблонами для анализа и категоризации разных типов input! Вы создадите систему, способную идентифицировать и описывать различные структуры data с помощью мощных возможностей сопоставления с шаблонами в Dart 3.
Вы организуете свой код в двух файлах:
classifier.dart: Создайте function с именемclassify, которая принимает параметрObjectи возвращает описание типаString. Используйте switch-выражение с сопоставлением с шаблонами для обработки следующих случаев:- Пустой list
[]должен возвращатьEmpty list - list ровно с одним целочисленным element должен возвращать
Single item: [value] - list ровно с двумя elements должен возвращать
Pair: [first] and [second] - list, начинающийся с целого числа, за которым следуют дополнительные elements, должен возвращать
List starting with [first], length: [total length](используйте rest-шаблон...) - map, содержащий оба ключа
'name'и'age', должен возвращать[name] is [age] years old(используйте деструктуризацию шаблона map) - Отрицательное целое число (используйте
whenclause) должно возвращатьNegative: [value] - Целое число, равное нулю, должно возвращать
Zero - Любое другое целое число должно возвращать
Positive: [value] - Любое другое значение должно возвращать
Unknown type
- Пустой list
main.dart: Импортируйте свой classifier и продемонстрируйте сопоставление с шаблонами на различных input. Выведите результат classify для каждого из следующих значений:- Пустой list
[] - list с одним element:
[42] - list с двумя elements:
['hello', 'world'] - Более длинный list:
[1, 2, 3, 4, 5] - map:
{'name': 'Alice', 'age': 25} - Целое число
-10 - Целое число
0 - Целое число
99
- Пустой list
Это challenge объединяет шаблоны list, шаблоны map, clause when для проверок и rest-шаблон (...) — все ключевые возможности сопоставления с шаблонами из урока!
Ожидаемый вывод:
Empty list
Single item: 42
Pair: hello and world
List starting with 1, length: 5
Alice is 25 years old
Negative: -10
Zero
Positive: 99Попробуйте сами
import 'classifier.dart';
void main() {
// TODO: Используйте функцию classify для категоризации каждого значения
// и выведите результаты
// Тест с пустым списком
print(classify([]));
// TODO: Тест со списком, содержащим один элемент: [42]
// TODO: Тест со списком, содержащим два элемента: ['hello', 'world']
// TODO: Тест с более длинным списком: [1, 2, 3, 4, 5]
// TODO: Тест с map: {'name': 'Alice', 'age': 25}
// TODO: Тест с целым числом -10
// TODO: Тест с целым числом 0
// TODO: Тест с целым числом 99
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыБиблиотеки и импортВведение в ООПКлассы и объектыКлючевое слово thisМетодыПеременные экземпляраОсновы конструкторовИтоги — Простой калькулятор4Null-безопасность
Введение в Null-безопасностьNullable и Non-Nullable типыОператоры ? и !Ключевое слово Late и Null-безопасностьNull-aware операторыNull-безопасность в классахИтоги — Система профилей пользователей7Абстрактные классы и интерфейсы
Абстрактные классыАбстрактные методыИнтерфейсы в DartНеявные интерфейсыРеализация против наследованияМножественные интерфейсыИтоги — Калькулятор фигур10Коллекции и обобщения
Обзор List, Set, MapТипобезопасные коллекцииОбобщенные классыОбобщенные методыОграничения обобщенийIterable и IteratorИтоги: Обобщенное хранилище13Продвинутые концепции ООП
Композиция против наследованияМетоды расширенияВызываемые классыЗапечатанные классы (Dart 3)Записи (Dart 3)Паттерны и сопоставление (3.0)Перечисления с методами16Проект: Управление библиотекой
Обзор проектаКлассы Book и User2Конструкторы в Dart
Конструктор по умолчаниюИменованные конструкторыСписки инициализацииКонстантные конструкторыФабричные конструкторыПеренаправляющие конструкторыИтоги — Shape Builder5Инкапсуляция
Публичные и приватные членыСоглашение о префиксе _Приватность на уровне библиотекГеттеры и сеттеры: подробный разборСкрытие данныхИтоги — Записи о студентах8Mixins
Введение в MixinsСоздание MixinsИспользование нескольких MixinsКлючевое слово on в MixinsMixin и наследованиеMixin и интерфейсИтоги: Система животных11Специальные методы
Переопределение toString()Переопределение hashCode и ==Интерфейс ComparableМетод call()Переопределение noSuchMethodПовторение — Пользовательская коллекция14Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн ObserverПаттерн Strategy3Свойства классов
Члены экземпляра и статические членыПоля Final и ConstПеременные LateСтатические методы и поляГеттеры и сеттерыИтоги — Менеджер банковского счета6Наследование
Основы наследованияКлючевое слово superПереопределение методовАннотация @overrideКлючевое слово final для классовКонструкторы и наследованиеИтоги: Иерархия сотрудников9Полиморфизм
Основы полиморфизмаПолиморфизм через интерфейсыПроверка типов во время выполненияОператоры is и asКлючевое слово covariantИтоги — Обработчик платежей12Асинхронное ООП
Futures и async/awaitОсновы StreamsКонтроллеры StreamАсинхронные конструкторыАсинхронность в методах классовИтоги — Data Fetcher15Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикПаттерн РепозиторийПотренируйтесь самостоятельно: Онлайн-компилятор Dart