一、 Patterns 是什么

下面是官方对 Patterns 特性的阐明 patterns :
从下面的第一句中能够知道,Patterns 是一种语法级的特性,而语法特性是一种言语的根基。

Patterns are a syntactic category in the Dart language, like statements and expressions.
Patterns 是 Dart 言语中的一个语法类别,就像语句和表达式一样。

从下面第二句话在能够看出,Pattern 和数据的特征匹配相关。

A pattern represents the shape of a set of values that it may match against actual values.
Pattern 表明可能与实践值相匹配的一组值的特征。

在英文中 Pattern 一词有:形式、方式、图样的意思。说句题外话:String 字符串和 Regex 正则表达式都完成 Pattern 接口,就阐明 Pattern 一词和形式匹配的渊源。这儿强调一句:Dart 3.0 的 Patterns 语法和上面提及的 Pattern 类型没有半毛钱关系。

在日常开发中,我们运用的类型都是具有必定的结构特征,而结构正是类中数据的栖身之地。Patterns 像是一种在语法层面,对类型结构特征提取的规矩,结合匹配来更方便地完成一些作业。在类型之中, Record、List、Map 三种类型,有着十分显着的结构特征:

记载 Record 类型
   |--- 一般值 (v1, v2 ,...)
   |--- 命名值 (k1:v1,k2:v2 ,...)
列表 List 类型 
   |--- 值列表 [v1,v2,...]
映射 Map 类型 
   |--- 键值对 {k1:v1, k2:v2 ,...}

二、 Patterns 的解构才能

解构(Destructuring) 便是拜访并提取目标的某些数据,为某些指定的变量进行赋值的过程。其中提取数据就需求运用到 Patterns 的匹配特性。下面经过几个小比方了解一下:

1.对 Record 类型的解构
  • 非命名 Record 的类型

如下 foo 中 : 默认情况下,想要拜访记载目标中的数据,需求经过 $1$2 :

void foo(){
  var user = ('toly',29);
  String name = user.$1;
  int age = user.$2;
  print('======$name====${age}===');
}

如下 foo1 中 : 能够运用 Patterns 的特性,直接将 user 目标解构,为 nameage 赋值。这便是 Patterns 最重要的才能之一,

void foo1() {
  var user = ('toly',29);
  var (name, age) = user; // 直接解构目标
  print('======$name====${age}===');
}

Record 的解构语法是 :

var ( 变量 1 , 变量 2 , … ) = Record 目标


  • 命名 Record 类型

关于元素被命名的 Record 类型而言, 能够经过如下 Patterns 语法进行解构。比方下面,一句代码就能够调试为 abc 三个变量赋值:

  var position = (x:1,y:3, 'p0');
  var (x:a, y:b ,c) = position;
  print('====$a====$b====$c====');

var ( k1: 变量 1, k2: 变量 2 , … ) = Record 目标

关于命名的数值而言,能够经过 :key 进行简写。比方下面的 :x 含义便是 x:x ,表明:将右侧目标中的名称为 x 的数据,为左边的 x 变量赋值。

var position = (x:1,y:3, 'p0');
var (:x,:y,d) = position;
print('====$x====$y====$d====');

这样的优点是能少起个变量名,合适 起名困难症者;但与此同时,这样你无法为变量名起其他名字。


2. 对 List 和 Map 的解构

除了 Record 类型 ,还有 List 和 Map 也支撑解构。效果上类似,都是拜访目标的数据,并直接为变量赋值。List 的结构语法是 :

var [ 变量1, 变量2, … ] = List 目标

void foo2(){
  List<int> numList = [1, 2, 3];
  var [a, b, c] = numList;
  print('====$a====$b====$c=');
}

如下是对 Map 目标的解构,语法是:

var { key : 变量1, key: 变量2, …} = Map 目标

void foo3(){
  Map<String,dynamic> data = {
      'name': 'toly',
      'age': 29,
    };
  var {'name': name,'age': age}= data;
  print('======$name====${age}===');
}

同理,关于 Map 元素组成的 List 列表,也能够经过对应的语法进行解构,只要左边变量结构契合右侧目标结构即可 :

void foo4(){
  var data = [
    {
      'name': 'toly',
      'age': 29,
    },
    {
      'name': 'ls',
      'age': 28,
    },
  ];
  var [{'name': name,'age': age},{'name': name1,'age': age2}] = data;
  print('======$name====${age}===$name1====${age2}====');
}

3. 对一般目标的解构

除了能够解构特定的目标之外,还能够对一般目标进行解构,但要留意 只要构造函数中的命名参数字段支撑解构。如下所示,界说了 Person 类:

class Person {
  final String name;
  final int age;
  Person({
    required this.name,
    required this.age,
  });
}

目标结构语法为:

var 类名( 命名字段1 : 变量1 , 命名字段2 : 变量2, …) = 目标

void foo5(){
  Person person = Person(name: 'toly', age: 29);
  var Person(name : a, age: b) = person;
  print('======$a====${b}===');
}

同样,如果懒得为变量起名字,也能够直接让字段名称为变量名:

var 类名( : 命名字段1 , : 命名字段2, …) = 目标

void foo5(){
  Person person = Person(name: 'toly', age: 29);
  var Person(:name, :age) = person;
  print('======$name====${age}===');
}

关于一般目标而言, get 办法也能够被形式匹配,用于解构。如下所示:Person 类中添加一个 nameLen 的get 办法,用于返回名字的长度:此刻能够经过 Person(nameLen: len) 匹配,将名称长度解构为 len 变量赋值:

Dart 3.0 语法新特性 |  模式匹配 Patterns

class Person {
  final String name;
  final int age;
  Person({
    required this.name,
    required this.age,
  });
  int get nameLen => name.length;
}

三、解构时需求留意的问题

1、解构结构的一致性

首先要留意的是,关于 List 、Record、Map 目标来说,左边的解构结构要和目标数据结构 彻底一致。 比方下面列表有三个元素,你只解构了两个,在运行时会报错。我觉得比较坑的是:

如果不一致的话,在 编辑期间 无法发觉,问题只能在运行时露出,这就或多或少存在必定的代码危险。

Dart 3.0 语法新特性 |  模式匹配 Patterns

同理,如果在解构 Map 目标时 key 写错了,在运行时也会报错:

Dart 3.0 语法新特性 |  模式匹配 Patterns


2、忽略解构单元

List 、Record、Map 目标的解构需求保持结构的一致性,但有时分并不需求彻底结构所有的数据,此刻能够运用 _ 来忽略对应的结构单元。

void foo8() {
  List<int> numList = [1, 2, 3];
  var [first, _,_] = numList;
  print('====$first====');
}

3、小结

本文从 解构 的视点,认识了一些常用类型的 Pattern 语法,下图是一个小结:

Dart 3.0 语法新特性 |  模式匹配 Patterns

从这儿我们或多或少能够体会出 Patterns 是一种 对形式的匹配。而解构是运用形式匹配的才能,从目标中提取数据为对应变量赋值。我们一开始就说了 Patterns 是一种语法级的特性,解构仅仅它的效果之一。而且形式也不仅仅针关于类型,某些运算符也能够作为形式的一部分。

本文简略认识一下 Patterns 的概念和在解构中的使用。别的,在流程控制中和匹配相关的有一个关键字 —- switch 。下一篇将从 switch 语法的改变,持续了解 Patterns 的效果。谢谢观看 ~