Применение pattern matching в языке Dart позволяет выполнить деструктуризацию - разложить некоторую структру данных или объект на отдельные компоненты (данный паттерн еще называется destructuring pattern).
Разложим кортеж на отдельные переменные:
void main() { var person = ("Sam", 29); var (name, age) = person; print("Name: $name"); print("Age: $age"); }
Здесь кортеж person раскладываем на две переменных - name и age. Эти переменные и их типы указываются также в круглых скобках.
var (String name, int age) = person;
Ключевое слово var фактически объявляет эти переменные. Но переменные также могут быть определены где-то ранее в программе:
void main() { var name = ""; var age = 0; var person = ("Sam", 29); (name, age) = person; print("Name: $name"); print("Age: $age"); }
Бывает, что нам нужны не все элементы кортежа. В этом случае для ненужных элементов можно передать символ подчеркивания _
void main() { var person = ("Sam", 29, "Google"); var (name, _, company) = person; print("Name: $name"); print("Company: $company"); }
Здесь пропускаем второй элемент кортежа. Подобным образом можно пропустить все элементы, которые нам не нужны:
void main() { var person = ("Sam", 29, "Google"); var (_, age, _) = person; print("Age: $age"); // 29 }
Если кортеж имеет именованные элементы, то при разложении их надо сопоставить с переменными:
void main() { var person = (name: "Sam", age: 29, company: "Google"); var (name: personName, age: _, company: personCompany) = person; print("Name: $personName"); print("Company: $personCompany"); }
В данном случае значение элемента name присваивается переменной personName, а значение элемента company - переменной personCompany. Значение элемента age в данном случае не важно, и для него используется символ-заместитель _.
Одним из распространенных сценариев применения разложения кортежа представляет обмен значениями:
void main() { int a = 15; int b = 50; (a, b) = (b, a); print("a = $a"); // a = 50 print("b = $b"); // b = 15 }
В данном случае запись (a, b) = (b, a)
фактически означает, что переменная a получает значение переменной b, переменная b - значение переменной a.
Аналогично разложению кортежа на элементы можно раскладывать и списки:
void main() { var numbers = [1, 2, 3]; var [a, b, c] = numbers; print("a=$a b=$b c=$c"); // a=1 b=2 c=3 }
С помощью символ-заместителя _ можно пропустить ненужные элементы
void main() { var numbers = [1, 2, 3]; var [a, _, c] = numbers; // пропускаем второй элемент print("a=$a c=$c"); // a=1 c=3 }
С помощью многоточия ... можно пропустить произвольное количество символов. Например, получим первый, второй и последний элементы списка:
void main() { var numbers = [1, 2, 3, 4, 5, 6, 7, 8]; var [a, b, ..., c] = numbers; print("a=$a b=$b c=$c"); // a=1 b=2 c=8 }
Подобным образом можно пропускать произвольное количество элементов в начале, середине и конце списка:
void main() { var numbers = [1, 2, 3, 4, 5, 6, 7, 8]; var [a, b, ...] = numbers; // получаем два первых элемента var [..., c, d] = numbers; // получаем два последних элемента print("a=$a b=$b c=$c d=$d"); // a=1 b=2 c=7 d=8 }
Dart также позволяет раскладывать объекты классов на отдельные значения. Например:
void main() { var tom = Person("Tom", 38); var Person(name: userName, age: userAge) = tom; print(userName); // Tom print(userAge); // 38 } class Person{ String name; int age; Person(this.name, this.age); }
Здесь объект класса Person расскладывается на две переменных - userName и userAge. При разложении сначала указываем имя класса и в скобках сопоставляем свойства класса с переменными
var Person(name: userName, age: userAge) = tom;