首页 > 其他分享 >Flutter/Dart第10天:Dart高级特性Pattern模式的全部类型(共15种)

Flutter/Dart第10天:Dart高级特性Pattern模式的全部类型(共15种)

时间:2023-10-05 22:12:18浏览次数:46  
标签:case 10 15 ... 模式 Dart var 匹配 子模式

Dart官方文档:https://dart.dev/language/pattern-types

重要说明:本博客基于Dart官网文档,但并不是简单的对官网进行翻译,在覆盖核心功能情况下,我会根据个人研发经验,加入自己的一些扩展问题和场景验证。

和操作符一样,模式运算也遵循一定的优先级规则,我们可以通过增加括号()让低优先级规则的模式优先运算:

  1. 逻辑或模式低于逻辑与模式,逻辑与模式低于关系模式:逻辑或 < 逻辑与 < 关系
  2. 一元模式优先级相同:值转换、空检测、空断言。
  3. 其他的模式都具有最高的优先级,集合类型(List列表、Map映射和Record记录)和对象模式包含了其他数据,因此作为外部模式优先运算。

逻辑或模式(Logical-or)

模式语法:子模式1 || 子模式2

模式规则:逻辑或模式通过||分割子模式,从左到右,任何一个子模式匹配则本模式匹配,且后面的子模式不在运算。

子模式可以绑定变量,但是每个子模式绑定的变量必须相同,因为任一子模式匹配则后面的子模式不在运算。

var isPrimary = switch (color) {
    Color.red || Color.yellow || Color.blue => true,
    _ => false
};

逻辑与模式(Logical-and)

模式语法:子模式1 && 子模式2

模式规则:逻辑与模式通过&&分隔子模式,从左到右,任何一个子模式未匹配则本模式未匹配,且后面的子模式不在运算。

子模式可以绑定变量,且每个子模式绑定的变量不能重叠,因为本模式匹配代表每个子模式都必须匹配运算,如果重叠则意味着变量被赋值多次。

switch ((1, 2)) {
  case (var a, var b) && (var c, var d): // ...
}

关系模式(Relational)

模式规则:关系模式通过和给定的常量进行比较完成匹配(比较操作符:==!=<><=>=),true代表匹配成功。通常情况下,关系模式和逻辑与模式配合使用。

String asciiCharType(int char) {
  const space = 32;
  const zero = 48;
  const nine = 57;

  return switch (char) {
    < space => 'control',
    == space => 'space',
    > space && < zero => 'punctuation',
    >= zero && <= nine => 'digit',
    _ => ''
  };
}

值转换模式(cast)

模式语法:变量 as 类型,如:foo as String

模式规则:值转换模式允许在对象数据解构过程中进行类型转换,如果类型无法转换,则会产生错误,建议在类型转换之前,进行类型断言。

(num, Object) record = (1, 's');
var (i as int, s as String) = record;

空检测模式(Null-check)

模式语法:子模式?

模式规则:如果检测的值不为NULL,则模式匹配。它允许绑定一个变量,变量的类型是该不可为NULL值类型基类。

String? maybeString = 'nullable with base type String';
switch (maybeString) {
  case var s?:
  // 's' has type non-nullable String here.
}

空断言模式(Null-assert)

模式语法:子模式!

模式规则:首先检测对象不为NULL,然后检测对象数据值。如果匹配的值为NULL,则会抛出错误。它常用于解构并赋值场景,且保证所赋值非NULL。

List<String?> row = ['user', null];
switch (row) {
  case ['user', var name!]: // ...
  // 'name' is a non-nullable string here.
}

(int?, int?) position = (2, 3);
var (x!, y!) = position;

常量模式(constant)

当值为常量时,常量模式匹配,常量包括:123, null, string, math.pi, SomeClass.constant, const Thing(1, 2), const (1 + 2)等。

switch (number) {
  // Matches if 1 == number.
  case 1: // ...
}

我们可以通过字面常量、命名的常量等方式使用常量模式:

  • 数字字面量:123, 45.56
  • 布尔字面量:true
  • 字符串字面量:string
  • 命名常量:someConstant, math.pi, double.infinity
  • 常量构造器:const Point(0, 0)
  • 常量集合字面量:const [], const {1, 2}

其他更多复杂的常量表达式,可以通过()包裹,并增加const前缀:const (const (1 + 2))

// List or map pattern:
case [a, b]: // ...

// List or map literal:
case const [a, b]: // ...

变量模式(variable)

模式规则:变量模式一般在解构和赋值中,它匹配模式、解构对象并完成赋值,如:var bar, String str, final int _。变量的作用域为模式所在的作用域。如果变量指定了类型,那么当对象类型和值均匹配时,模式才被匹配。通配符模式是一个特殊的变量模式。

switch ((1, 2)) {
  // 'var a'和'var b'是变量模式,它们值分别为`1`和`2`
  case (var a, var b): // ...
  // 'a'和'b'的作用域在case代码块
}

switch ((1, 2)) {
  // `2`是数字类型,与'String b'不匹配,因此本模式为匹配
  case (int a, String b): // ...
}

标识符模式(identifier)

标识符模式与常量模式或变量模式类似:

  • 变量申明上下文:给变量申明一个标识符,如:var (a, b) = (1, 2);
  • 变量赋值上下文:给已经存在的标识符赋值,如:(a, b) = (3, 4);
  • 模式匹配上下文:当作一个命名常量模式(除名字是_外)
  • 任意上下文中的通配符标识符:能匹配任何值且忽略该值,如:case [_, var y, _]: print('The middle element is $y');

括号模式

模式语法:(子模式)

代码样例:如下代码,和表达式一样,增加括号()目的是提高模式的优先级。

final (x, y, z) = (true, true, false);

// 没有括号:true
x || y && z => 'matches true',

// 增加括号:false
(x || y) && z => 'matches false',

列表模式(List)

模式语法:[子模式1, 子模式2]

List列表模式首先匹配List类型,然后匹配列表元素值,并进行解构和赋值。List列表模式必须匹配整个列表模式元素,我们可以使用...占位符匹配剩余的列表元素。

// 全列表元素匹配
const a = 'a';
const b = 'b';
switch (obj) {
  case [a, b]:
    print('$a, $b');
}

// 占位符匹配剩余元素,且忽略
var [a, b, ..., c, d] = [1, 2, 3, 4, 5, 6, 7];
print('$a $b $c $d'); // 1 2 6 7

// 占位符当作一个子列表
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

Map映射模式

模式语法:{"key": subpattern1, someConst: subpattern2}

Map映射模式首先匹配Map类型,然后匹配元素内容,并进行解构和赋值。Map映射模式不需要匹配所有元素,忽略未被匹配到的元素。

Record记录模式

模式语法:(subpattern1, subpattern2)或者(x: subpattern1, y: subpattern2)

Record记录模式首先匹配记录,然后解构其字段。字段数量、类型和值未匹配,则模式匹配失败。Record记录模式必须匹配所有字段。字段getter可由变量和标识符模式推导得到。

var (myString: foo, myNumber: bar) = (myString: 'string', myNumber: 1);

// Record pattern with variable subpatterns:
var (untyped: untyped, typed: int typed) = record;
var (:untyped, :int typed) = record;

switch (record) {
  case (untyped: var untyped, typed: int typed): // ...
  case (:var untyped, :int typed): // ...
}

// Record pattern wih null-check and null-assert subpatterns:
switch (record) {
  case (checked: var checked?, asserted: var asserted!): // ...
  case (:var checked?, :var asserted!): // ...
}

// Record pattern wih cast subpattern:
var (untyped: untyped as int, typed: typed as String) = record;
var (:untyped as int, :typed as String) = record;

Object对象模式

模式语法:SomeClass(x: subpattern1, y: subpattern2)

对象模式首先对象类型和属性类型,并完成对象属性解构,调用getter方法完成赋值。如果类型不一致,则匹配失败。对象的属性名可以忽略,它可以通过变量模式和标识符模式进行推导。和Map映射模式一样,对象模式不需要匹配所有属性,忽略未被匹配到的属性。

switch (shape) {
  // Matches if shape is of type Rect, and then against the properties of Rect.
  case Rect(width: var w, height: var h): // ...
}

// Binds new variables x and y to the values of Point's x and y properties.
var Point(:x, :y) = Point(1, 2);

通配符模式

模式语法:_
_就是通配符模式,它既是变量模式也是标识符模式,但是它无变量也不赋值。它通常作为一个占位符,目的是匹配解构剩下的位置值。通配符如果带有类型,那么它仅仅进行类型检测,而忽略变量和赋值。

// 占位符
var list = [1, 2, 3];
var [_, two, _] = list;

// 类型检测
switch (record) {
  case (int _, String _):
    print('First field is int and second is String.');
}

我的本博客原地址:https://ntopic.cn/p/2023100501


标签:case,10,15,...,模式,Dart,var,匹配,子模式
From: https://www.cnblogs.com/obullxl/p/NTopic2023100501.html

相关文章

  • 74th 2023/10/5 模拟赛总结56
    T1看完题目,看到n<=9的限制,心头一紧一个词汇浮现于心:BruceForces暴力+记忆化,\(O(能过)\)但赛时并没有这样打,而是选择了往DP方面思考因为真的没想到能过然后DP呢,又不清楚该如何存一列的状态就匆匆暴力后离去考虑状压DP保留有用状态关键点:\(k=\min(k,n-k)\)可以参考\(C^k......
  • PAT 甲级:1002 A+B for Polynomials,测试点说明
     1002A+BforPolynomials25分题解:(类似于把两个多项式合并同类项:指数相同的项把系数相加),最后输出新多项式的项数、各项。 需要注意的测试点:1.输出的新项格式要与输入的一致:[项数][指数1][系数1][指数2][系数2]...;且指数递减2.指数是整型,系数是浮点型;且最后输出......
  • 73rd 2023/10/4 模拟赛总结55&广义串并联图
    这次的比赛成绩并不令人失望,因为早有准备很用心去打的一场比赛,T1T2一开始在看题目时感觉可以很容易切掉T1感觉太简单了,就再看了一遍又一遍T2动手打的时候,感觉T1没那么简单,就在想了一下,想出来了正解,但给的第三个大数据总过不了然后就先放了一下T1,去打T2,因为感觉T2很简单,而且思......
  • 2023-2024-1 20231415吴昕洋 《计算机基础与程序设计》第一周学习总结
    这个作业属于哪个课程2023-2024-1-计算机基础与程序设计这个作业要求是什么2023-2024-1-计算机基础与程序设计第一周作业这个作业的目标简单浏览《计算机概论》,提出疑问,并尝试解决问题作业正文https://i.cnblogs.com/posts/edit教材内容·学习总结  ......
  • 231005.md
    2023/10/05模拟赛总结时间安排07:55-08:30起晚了。看题,写了下A的四方,卡了卡常发现跑的有点快,写B。08:30-09:10卡A常数,加了些大优化。09:10-09:40拼C的前几个包。09:40-11:00写D,拍A,B。11:00-11:40写C的大暴力dp。总结反思写题太慢了。节奏......
  • 2023/10/5软件工程日报
    今天用vue向后端发送请求时发生了跨域的问题,记录下来vue.config.js: App.vue:发送axios请求时就不用加上localhost。。。。等了 ......
  • 20231004
    23/10/04NOIP模拟赛总结时间安排7:40-8:00看题,感觉都没有思路,有点慌。8:20-9:00思考T1,先把暴力打了,打表找规律找了20分钟。9:00-9:30写T2暴力,感觉前两题都是DP,但不会设状态,原因在反思总结中有提到。9:30-10:20想到了T3的\(n^2\)做法,但是没想明白细节,弃疗。10:20-11:0......
  • 23/10/05 模拟赛总结
    时间安排7:40-7:50读题,毫无思路。7:50-8:10尝试写A题暴力,发现写不出来。8:10-8:30写了B题爆搜。8:30-9:30罚坐,想了一会D题,毫无思路。9:30-10:00读懂了C题,会了链的部分分,写的时候会了“正解”(随机图复杂度\(O(n\logn)\),菊花图复杂度\(O(n^2)\))。10......
  • [ARC154E] Reverse and Inversion
    2023-09-09题目[ARC154E]ReverseandInversion难度&重要性(1~10):9.5题目来源luogu题目算法数学解题思路Update:2023.8.28修改一处笔误这是一道很妙的计数题,考试的时候没想到。这道题我们首先会想到去化简一下式子\(\sum\limits_{i<j,p_i>p_j}(j-i)\),这很明显是要......
  • 10.05模拟赛总结
    比赛传送门总结\(100+60+0+0=160\),Rank16,寄寄寄寄寄。T1优秀\(\texttt{/}\)\(\texttt{Good}\)题意求\(l\)和\(r\)之间的\(2\)的整数次幂。分析解法1由于\(l\)和\(r\)非常小,所以可以直接模拟,没啥好说的。时间复杂度\(O(r)\)。解法2充分发扬人类智慧,发......