模式
Dart 3.0引入了一个非常强大的功能,模式(Pattern)。一般来说,依据模式的形状及其上下文, 模式可以匹配(match)或解构(destructure)一个值,匹配与解构可同时进行。
匹配
模式匹配可以检查一个值是否:
- 具有特定的形状;
- 是特定常数;
- 等于某个值;
- 有特定的数据类型。
这么说还是有点抽象,我们来看下面的示例。
//ex311.dart
void main() {
const numbers = [1, 2, 3]; // 1
if (numbers case [_, _, _]) { // 2
print('numbers is a list which has 3 elements.');
}
if (numbers case [1, 2, 3]) { // 3
print('numbers is exactly [1, 2, 3].');
}
const point = (x: 3, y: 4); // 4
if (point case (x: _, y: _)) { // 5
print("point is a record with named fields x and y.");
}
}
- 声明了一个
const列表numbers; - 检查
numbers是否是一个具有2个元素的列表; - 检查
numbers是否就等于[1, 2, 3]; - 声明一个记录
point; - 检查
point是否是一个具有命名字段x和y的记录(record)。
解构
模式解构提供了一种便捷的声明式语法,可以将一个值分解成各部件(parts),并将部分或全部的部件,绑定至局部变量。
//ex312.dart
void main() {
const numbers = [1, 2, 3];
if (numbers case [var a, var b, _]) { // 1
print('a=$a b=$b');
}
if (numbers case [var a, ...var rest]) { // 2
print('The first element is $a, and the rest is $rest');
}
const point = (x: 3, y: 4);
if (point case (x: var a, :var y)) { // 3
print("a=$a y=$y");
}
}
- 匹配
numbers并绑定前2个元素至变量a和b; - 匹配
numbers并绑定第1元素至变量a,绑定剩余的元素至变量rest,注意var rest之前有3个点(....); - 匹配
point,并将其x字段绑定至变量a,y字段绑定至变量y;这里的:var y乃y:var y的简便写法。
下面是与类相关的模式匹配的一个示例:
// ex313.dart
void main() {
const point = Point(3, 4); // 4
if (point case Point(:var x, :var y, :var z)) { // 5
print("x=$x, y=$y, z=$z");
}
}
class Point {
const Point(this.x, this.y); // 1
final int x; // 2
final int y; // 2a
int get z => x + y; // 3
}
- 这是类
Point的构造函数; x与y是Point的两个公开的字段;z是 getter 方法,由x和y计算而成,形式上当成字段来用;- 声明一个变量
point,它Point类的一个实例; - 解构
point,并将其部件分别绑定值变量x、y、z。
解构不但可以绑定字段,还可以绑定函数/方法(在类中定义的函数),也就是为什么在描述解构时,采用了部件(而非字段)这个词。
// ex314.dart
void main() {
const rect = Rectangle(5, 6);
if (rect case Rectangle(:var area)) {
print("${area(.1)} m²");
}
}
class Rectangle {
const Rectangle(this.a, this.b);
final double a;
final double b;
double area([double unit = 1]) => a * b * unit * unit;
}