dart的模式匹配与解构

219 阅读3分钟

前言

模式匹配与模式的解构,主要用于记录类型(Records)的匹配与读取元素的值。延伸到其他的集合类型也可以使用模式匹配与模式解构。使用switch-case语句、if-case语句、switch表达式进行模式匹配与模式解构。

简单示例: 下面示例展示了不带命名参数的Records数据与带命名参数的Records数据,在模式匹配与模式解构的用法。

void main(){
    final person = ('小明', 18); // 不带命名参数
    final person1 = (name: '小王', age: 18); // 带命名参数
    // 直接读取
    print('姓名:${person.$1}, 年龄:${person.$2}');
    
    // 模式解构
    caseTest(person); //输出: 不带命名参数 姓名:小明 年龄:18
    caseTest(person1); //输出:带命名参数 姓名:小王 年龄:18
}

void caseTest(Object value) {
    switch(value) {
        case (String name, int age):
            print('不带命名参数 姓名:$name 年龄: $age');
            
        // 也可以用 case (name: String name, age: int age)    
        case (:String name, :int age):
            print('带命名参数 姓名:$name1 年龄:$age');
    }
}

模式匹配

模式匹配分为:

  • 匹配值
  • 匹配类型

1、匹配值

  • 完全匹配 所有的数据的值相等
final person = ('小明',18);

/// 匹配完整的值 switch-case语句
switch (person) {
    case ('小明', 18):
        print('匹配成功');
}

/// 匹配完整的值 if-case语句
if (person case ('小明', 18)) {
    print('匹配成功');
}
  • 部分匹配(忽略某个值的匹配)
final person = ('小明',18);

/// switch-case
switch (person) {
    case (_, 18):
        print('匹配年龄为18的人');
}
  • 匹配某个值可多选
final person = ('小明',18);

switch (person) {
    case ('小明' || '小王', 18):
        print('小明 和 小王,年龄为18岁');
}

2、匹配类型

一般用is判断类型,这里只需要知道,还能进行类型的判断。

final person = ('小明', 18);

switch(person) {
    case (String _, int _):
        print('匹配类型成功');
}

/// 当然这里类型判断可以用is进行判断
if (person is (String, int)) {
    print('类型匹配成功');
} 

模式解构

模式解构分为:

  • 声明时解构
  • 匹配时解构

1、声明时解构

final (name, age) = ('小明', 18);

// or
final (name: name,age: age) = (name: '小明', age: 18);

// or 
final (:name, :age) = (name: '小明', age: 18); 

2、匹配时解构

  • 不带命名参数的Records解构
final person = ('小明', 18);

switch (person) {
    case (String name, int age):
        print('name:${name} age:$age');
}
  • 带命名参数的Records解构
final person = (name: '小明', age: 18);

switch (person) {
    case (:String name, :int age):
        print('name:${name} age:$age');
}
  • Map类型数据解构
final person = {'name': '小明', 'age': 18};

switch (person) {
    case {'name': String name, 'age': int age}:
        print('name:${name} age:$age');
}

带条件的模式匹配

switch (shape) {
  case Square(size: var s) || Circle(size: var s) when s > 0:
    print('Non-empty symmetric shape');
}

最佳实践

  • 解决多层嵌套
void validData(bool b1, bool b2, bool b3) {
    final data = (b1, b2, b3);
    switch (data) {
        case (true,true,true):
            print('全部通过');
        case (true, true, false):
            print('条件3未通过');
        case (true, false, true):
            print('条件2未通过');
        case (true, false, false):
            print('条件2未通过,条件3未通过');
        default:
            print('默认处理');
    }
}
  • 利用完备性检查,实现枚举类
sealed class Shape {}

class Square implements Shape {
  final double length;
  Square(this.length);
}

class Circle implements Shape {
  final double radius;
  Circle(this.radius);
}

double calculateArea(Shape shape) => switch (shape) {
   Square(length: var l) => l * l,
   Circle(radius: var r) => math.pi * r * r
};