Menu
Coddy logo textTech

Паттерны и сопоставление (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 в списке. Подчёркивание _ действует как подстановочный символ, который сопоставляется с чем угодно. В сочетании с запечатанными классами шаблоны обеспечивают исчерпывающую и типобезопасную обработку сложных структур данных.

challenge icon

Задание

Легко

Давайте создадим 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)
    • Отрицательное целое число (используйте when clause) должно возвращать Negative: [value]
    • Целое число, равное нулю, должно возвращать Zero
    • Любое другое целое число должно возвращать Positive: [value]
    • Любое другое значение должно возвращать Unknown type
  • 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

Это 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
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Онлайн-компилятор Dart