模式
Dart 3.0引入了一个非常强大的功能,模式(Pattern)。一般来说,依据模式的形状及其上下文, 模式可以匹配(match)或解构(destructure)一个值,匹配与解构可同时进行。
匹配
模式匹配可以检查一个值是否:
- 具有特定的形状;
- 是特定常数;
- 等于某个值;
- 有特定的数据类型。
这么说还是有点抽象,我们来看下面的示例。
//ch0301_1.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),并将部分或全部的部件,绑定至局部变量。
//ch0301_2.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
的简便写法。
下面是与类相关的模式匹配的一个示例:
// ch0301_3.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
。
解构不但可以绑定字段,还可以绑定函数/方法(在类中定义的函数),也就是为什么在描述解构时,采用了部件(而非字段)这个词。
// ch0301_4.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;
}