1. Логический шаблон ИЛИ A || B
Совпадает с любым подшаблоном; все ветви должны определять полностью одинаковый набор переменных.
enum Color { red, yellow, blue, green }
void main() {
Color c = Color.red;
bool primary = switch(c) {
Color.red || Color.yellow || Color.blue => true,
_ => false
};
print(primary); // true
}Code language: Dart (dart)
2. Логический шаблон И A && B
Оба подшаблона должны совпадать одновременно; подшаблоны не могут привязывать переменные с одинаковым именем.
void main() {
switch((2, 3)) {
// Ошибка: оба подшаблона привязывают переменную b, конфликт имен
// case (var a, var b) && (var b, var c): print("ok");
case (var a, var b) && (>1, <5):
print("a=$a,b=$b"); // a=2,b=3
}
}Code language: Dart (dart)
Запись (>1, <5) означает, что первое число должно быть больше 1, а второе меньше 5.
3. Относительный шаблон < > <= >= == !=
Используется для проверки числовых диапазонов, часто сочетается с && для ограничения границ значений
String asciiCharType(int charCode) {
const space = 32, zero = 48, nine = 57;
return switch(charCode) {
< space => "Управляющий символ",
== space => "Пробел",
> space && < zero => "Знак препинания",
>= zero && <= nine => "Цифра",
_ => "Другое"
};
}
void main() {
print(asciiCharType(50)); // Цифра
print(asciiCharType(33)); // Знак препинания
}Code language: Dart (dart)
В данном примере используется код ASCII для классификации управляющих символов, цифр и знаков. Правила проверки charCode в switch: меньше 32 — управляющий символ, равно 32 — пробел, между 32 и 48 — знаки препинания, от 48 до 57 включительно — цифры, остальное относится к категории «другое».
4. Шаблон принудительного преобразования типа sub as Type
Выполняет явное преобразование типа во время деструктуризации; при несоответствии типов выбрасывает исключение во время выполнения
void main() {
(num, Object) rec = (10, "hello");
var (i as int, s as String) = rec;
print(i + 5); // 15
print(s.toUpperCase()); // HELLO
}Code language: Dart (dart)
В примере запись rec разбивается на переменные i и s. Если первый элемент не целое число, а второй не строка — возникнет runtime-исключение.
Ниже приведён пример с ошибкой:
void main() {
(num, Object) rec = (9.3, "hello");
var (i as int, s as String) = rec;
print(i + 5); // 15
print(s.toUpperCase()); // HELLO
}Code language: Dart (dart)
D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
Unhandled exception:
type 'double' is not a subtype of type 'int' in type cast
#0 main (file:///D:/dartdemo/firstdart/bin/firstdart.dart:3:10)
#1 _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:314:19)
#2 _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:193:12)Code language: PHP (php)
5. Шаблон проверки на null sub?
Совпадает только с непустым значением; внутренние переменные автоматически повышаются до неподдерживающих null типов. При значении null совпадение не происходит, исключений не генерируется.
void main() {
String? str = "test";
switch(str) {
case var s?:
print(s.length); // s — строка без null, вывод 4
case null:
print("Пустое значение");
}
}Code language: Dart (dart)
6. Шаблон утверждения не-null sub!
Совпадает только с непустым значением; если значение равно null — сразу выбрасывает runtime-исключение
void main() {
List<String?> row = ["user", "bob"];
switch(row) {
case ["user", var name!]:
print(name); // name — строка без null
}
// Использование при деструктуризации переменных
(int?, int?) pos = (2, 3);
var (x!, y!) = pos;
print(x + y);
}Code language: Dart (dart)
Разбор записи var name!
var name:Переменный шаблон — ключевое словоvarобъявляет новую локальную переменнуюnameи привязывает подходящее значение при совпадении;!:Постфиксный шаблон утверждения не-null — требует, чтобы значение не было равным null; при null возникает ошибка во время выполнения.
Общее значение: var name! создаёт новую переменную name и одновременно гарантирует, что её значение не может быть null.
7. Константный шаблон
Литералы, именованные константы, конструкторы const и коллекции const относятся к константным шаблонам; совпадение возникает при полном равенстве значений
Поддерживаемые типы: числа, строки, булевы значения, именованные константы, объекты / списки с модификатором const
void main() {
const target = 10;
int num = 10;
switch(num) {
case 1: print("Один");
case target: print("Совпадает с константой 10");
case const [1,2]: print("Константный список");
default: print("Другое");
}
}Code language: Dart (dart)
Результат выполнения программы
Совпадает с константой 10
8. Переменный шаблон var x / int x / final x
При успешном совпадении привязывает новую локальную переменную; аннотация типа одновременно проверяет тип значения
void main() {
switch((99, "dart")) {
case (int a, String b):
print("$a $b"); // 99 dart
case (int a, int b):
print("Два числовых значения");
}
}Code language: Dart (dart)
9. Идентификаторный шаблон
Поведение разделяется на три контекста:
- Контекст объявления
var (a,b):Создаёт новые переменные - Контекст присваивания
(a,b) = val:Перезаписывает существующие переменные - Контекст сопоставления switch:Обрабатывается как константа (исключение —
_)
void main() {
const c = 5;
int val = 2;
switch(val) {
case c: print("Совпадает с константой c");
default: print("Совпадения нет"); // Выполняется эта строка
}
}
Code language: Dart (dart)
10. Скобочный шаблон (subPattern)
Изменяет приоритет операторов шаблона для разделения порядка вычисления || и &&
void main() {
bool x = true, y = true, z = false;
bool test = switch(true) {
(x || y) && z => true,
_ => false
};
print(test); // false
}
Code language: Dart (dart)
11. Шаблон списка
Совпадает с объектами List и разбирает элементы по позиции; поддерживает оператор rest ... для захвата любого количества оставшихся элементов
1. Базовое сопоставление списка
void main() {
const a = "a", b = "b";
var arr = ["a", "b"];
switch(arr) {
case [a, b]: print("Совпадение найдено");
default: print("Совпадения нет");
}
}Code language: Dart (dart)
2. Захват остаточных элементов через rest
void main() {
var [a, b, ...rest, c, d] = [1,2,3,4,5,6,7];
print("$a $b $rest $c $d"); // 1 2 [3, 4, 5] 6 7
}
Code language: Dart (dart)
D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
1 2 [3, 4, 5] 6 7Code language: CSS (css)
12. Шаблон Map {"key": subP}
Совпадает с объектами Map и проверяет только указанные ключи; при отсутствии нужного ключа генерируется StateError, лишние неупомянутые ключи игнорируются
void main() {
var data = {"user": ["Lily", 13]};
if(data case {"user": [String name, int age]}) {
print("$name $age"); //Lily 13
}
}Code language: JavaScript (javascript)
13. Шаблон записей (Record)
Два варианта: позиционная запись (p1,p2), именованная запись (k:p1,k2:p2)
Поддерживается сокращённая запись :var для исключения повторяющихся имён полей
void main() {
// Деструктуризация позиционной записи
var (name, age) = ("Doug", 25);
// Сокращённая деструктуризация именованных полей
final (:name, :age) = (name: "Tom", age: 18);
}
Code language: JavaScript (javascript)
14. Шаблон объекта Class(prop: p)
Совпадает с объектами указанного типа и разбирает свойства геттеров; поддерживается сокращение :var
class Point {
final int x, y;
Point(this.x, this.y);
}
void main() {
Point p = Point(10, 20);
var Point(:x, :y) = p;
print("$x $y");
}
Code language: JavaScript (javascript)
15. Шаблон подстановочного символа _
Совпадает с любым значением без привязки переменной; используется как заполнитель или только для проверки типа без извлечения значения
void main() {
var arr = [1,2,3];
var [_, mid, _] = arr;
print(mid); // 2
switch((10, "abc")) {
case (int _, String _):
print("Типовое совпадение успешно");
}
}Code language: JavaScript (javascript)
Pattern