Dart 3.0 语法新特性 | Records 记录类型 (元组)

news2024/11/30 8:39:56

theme: cyanosis

终于,终于,终于, Dart 支持元组了! 官方称之为 Records 特性,所以入乡随俗,以后中文称之为 记录类型 。官方 对它的介绍 是:

Records are an anonymous, immutable, aggregate type.
记录是一种匿名的、不可变的聚合类型。


1. 记录类型的声明与访问

通过 () 将若干个对象组合在一块,作为一个新的聚合类型。定义时可以直接当放入对象,也可以进行命名传入:

``` var record = ('first', a: 2, b: true, 'last'); print(record.runtimeType);

--->[打印输出]--- (String, String, {int a, bool b}) ```

上面的 record 对象由四个数据构成,通过 runtimeType 可以查看到其运行时类型,类型为各个非命名数据类型 + 各命名类型。

非命名类型数据可以通过 $index 进行访问:

``` print(record.$1); print(record.$2);

--->[打印输出]--- first last ```

命名类型数据可以通过 名称 进行访问:

``` print(record.a); print(record.b);

--->[打印输出]--- 2 true ```

注意: 一个记录对象的数据不允许被修改:

image.png


2. 记录类型声明对象

一个 Records 本质上也是一种类型,可以用该类型来声明对象,比如现在通过 (double,double,double) 的记录类型表示三个坐标,如下定义 p0 和 p1 对象:

void main() { (double x, double y, double z) p0 = (1, 2, 3); (double x, double y, double z) p1 = (1, 2, 6); }

既然可以实例化为对象,那么自然也可以将其作为参数类型传入函数中,如下 distance 方法传入两个三维点,计算距离:

double distance( (double x, double y, double z) p0, (double x, double y, double z) p1, ) { num result = pow(p0.$1 - p1.$1, 2) + pow(p0.$2 - p1.$2, 2) + pow(p0.$3 - p1.$3, 2); return sqrt(result); }

但记录类型一旦显示声明,写起来比较繁琐;和函数类型类似,也可以通过 typedef 来定义类型的别名。如下所示,定义 Point3D 作为别名,功能是等价的,但书写和可读性会更好一些:

``` typedef Point3D = (double, double, double);

void main() { Point3D p0 = (1, 2, 3); Point3D p1 = (1, 2, 6);

print(distance(p0, p1)); }

double distance(Point3D p0, Point3D p1) { num result = pow(p0.$1 - p1.$1, 2) + pow(p0.$2 - p1.$2, 2) + pow(p0.$3 - p1.$3, 2); return sqrt(result); } ```

同理,记录类型也可以作为返回值,这样可以解决一个函数返回多值的问题。如下 addTask 方法可以计算 1 ~ count 的累加值,返回计算结果和耗时毫秒数:

dart ({int result, int cost}) addTask2(int count) { int start = DateTime.now().millisecondsSinceEpoch; int sum = 0; for (int i = 0; i < count; i++) { sum += i; } int end = DateTime.now().millisecondsSinceEpoch; return ( result: sum, cost: end - start, ); }


3. 记录类型对象的等值

记录类型会根据字段的结构自动定义 hashCode 和 == 方法。 所以两个记录对象相等,就是其中的各个数值相等。但是通过 identical 可以看出 p0 和 p1 仍是两个对象,内存地址不同:

``` (double, double, double) p0 = (1, 2, 3); (double, double, double) p1 = (1, 2, 3); print(p0 == p1); print(identical(p0, p1));

--->[打印输出]--- true false ```

如下所示,第二个数据是 List<double> 类型,两个 [2] 是两个不同的对象,所以 p2,p3 不相等:

``` (double, List , double) p2 = (1, [2], 3); (double, List , double) p3 = (1, [2], 3); print(p2==p3);

--->[打印输出]--- false ```

下面测试中, 列表使用同一对象,则 p2,p3 相等:

``` List li = [2]; (double, List , double) p2 = (1, li, 3); (double, List , double) p3 = (1, li, 3); print(p2==p3);

--->[打印输出]--- true ```


4. 记录类型的价值

对于编程语言来说,Dart 的记录类型也不是什么新的东西,就是其他语言中的元组。如下所示,可以创建一个 TaskResult 类来维护数据作为返回值。但如果只是返回一些临时的数据,为此新建一个类来维护数据就会显得比较繁琐,还要定义构造函数。

```dart class TaskResult{ final int result; final int cost;

TaskResult(this.result, this.cost); }

TaskResult addTask(int count) { int start = DateTime.now().millisecondsSinceEpoch; int sum = 0; for (int i = 0; i < count; i++) { sum += i; } int end = DateTime.now().millisecondsSinceEpoch; return TaskResult(sum, end - start); } ```


除此之外,一个函数返回多个数据也可以使用 Map 对象:

```dart Map addTask(int count) { int start = DateTime.now().millisecondsSinceEpoch; int sum = 0; for (int i = 0; i < count; i++) { sum += i; }

int end = DateTime.now().millisecondsSinceEpoch; return { 'result' : sum, 'cost': end - start }; } ```

但这种方式的弊端也很明显,返回和使用时都需要固定的字符串作为 key。如果 key 写错了,代码在运行前也不会有任何错误,这样很容易出现风险。多人协作时,而且如果函数的书写者和调用者不是一个人,那该使用什么键得到什么值就很难分辨。

Map<String,dynamic> task = addTask2(100000000); print(task['result']); print(task['cost']);

所以,相比于新建 class 或通过 Map 来维护多个数据,使用记录类型更加方便快捷和精确。但话说回来,如果属性数据量过多,使用记录类型看起来会非常麻烦,也不能定义成员方法来操作、修改内部数据。所以它有自己的特点使用场景,比如临时聚合多个数据来方便使用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/527903.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

I3C仿真:PGY I3C-EX-PD使用

简述 本文所使用的I3C仿真软件是由Prodigy Technovations Pvt. Ltd公司所研发的MIPI PGY-I3C-EX-PD I3C仿真设备&#xff0c;这款设备搭载了配套软件&#xff0c;专门用于模拟I3C设备&#xff0c;它可以实现模拟Master、SLAVE&#xff0c;同时也支持模拟I2C Slave&#xff0c…

sklearn中的特征工程(过滤法、嵌入法和包装法)

目录 ​编辑特征工程的第一步&#xff1a;理解业务 Filter过滤法 ​编辑方差过滤 ​编辑- 相关性过滤 - 卡方过滤 - F检验 - 互信息法 ​编辑嵌入法&#xff08;Embedded&#xff09; 包装法&#xff08;Wrapper&#xff09; 特征工程的第一步&#xff1a;理解业务 如…

公司大数据CDH技术选型升级为EMR集群的技术调研

大数据技术栈现状 大数据技术整体设计图 当前大数据各组件版本 ZooKeeper 3.4.5 Spark 2.4.0 Hue 4.3.0 Hive 2.1.1 Hbase 2.1.4 Hadoop 3.0.0 Kafka 2.2.1 Phoenix 5.0.0-cdh6.2.0 Dolphinscheduler 3.0.0 Yarn 3.0.0-cdh6.3.2 Logstash 7.7.0 Kibana 7.7.0 Elasticsearch 7…

反涉网犯罪研究 | 电商平台自动收货代码审计

0x00 免责声明 本文仅限于学习讨论与反诈知识的分享&#xff0c;不得违反当地国家的法律法规。对于传播、利用文章中提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;本文作者不为此承担任何责任&#xff0c;一旦造成后果请自行承担…

信息发布系统在医院体检中心的运用

随着生活水平条件的提高&#xff0c;大家的健康意识更加强&#xff0c;重视体检的人数也越来越多&#xff0c;因此体检中心&#xff0c;医院体检门诊中心人流量都很大&#xff0c;健康市场空间前景大&#xff0c;各种医疗健康机构快速发展&#xff0c;市场竞争激烈&#xff0c;…

Linux——互斥和同步(二)

目录 信号量 读写信号量 互斥量 RCU机制 虚拟串口驱动加入互斥 完成量 习题 信号量 前面所讨论的锁机制都有一个限制&#xff0c;那就是在锁获得期间不能调用调度器&#xff0c;即不能引起进程切换。但是内核中有很多函数都可能会触发对调度器的调用&#xff08;在中断的…

Win10笔记本开机黑屏出现白色错误英文无法启动怎么办?

Win10笔记本开机黑屏出现白色错误英文无法启动怎么办&#xff1f;有用户电脑正常开机之后&#xff0c;出现了问题&#xff0c;系统无法正常的启动&#xff0c;出现一些英文错误代码。那么遇到这个情况怎么去进行解决呢&#xff1f;一起来看看以下的解决方法分享吧。 准备工作&a…

C语言数据结构注意点-线性表

目录 关于指针 LinkList L和LinkList *L的区别 初始化注意点 scanf()的操作 顺序表相关操作符号的确定 关于指针 ①指针和指针变量是两个不同的概念&#xff0c;但要注意的是&#xff0c;通常我们叙述时会把指针变量简称为指针。 ②指针变量其实是一个变量&…

FL Studio21中文完整版All Plugins Edition及切换教程

说到制作电音的软件&#xff0c;coco玛奇朵一定会把FL Studio放到第一个来讲。水果是一款为了电子音乐而生的的宿主软件。水果&#xff0c;独特的节拍音序器组件和通道机架与混音台模块打造的编曲“块”的思路。是极为适合于电子音乐的编排。而且随着水果版本不断地升级&#x…

Vite的基本介绍以及优劣势(一文读懂vite)?

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、Vite是什么&#xff1f;二、为什么选Vite?1、现实的问题2、缓慢的服务器启动3、缓慢的更新 三、Vite的优势&#xff1f;四、Vite的劣势&#xff1f;五、Vite以…

深入理解双亲委派机制

一、双亲委派机制委派流程 双亲委派机制&#xff0c;就是JVM虚拟机加载类的时候&#xff0c;会优先委派上级类加载器进行类加载。 1、如果上级类加载器能找到这个类&#xff0c;那就由上级类加载器加载&#xff0c;并且对下级共享&#xff0c;反之不共享。 2、如果上级类加载…

【#ifndef, #define, 和 #endif】

前言 学习AFNetWoring源码的时候&#xff0c;在AFN的h借接口文件又看到了这几个宏定义&#xff0c;学习记录一下。 作用 #ifndef, #define, 和 #endif是C/CPP的预处理指令&#xff0c;常常用来条件编译和防止头文件重复包含。 简介 #ifndef 它是if not define的简写&…

SpringBoot 使用 Sa-Token 完成注解鉴权功能

注解鉴权 —— 优雅的将鉴权与业务代码分离。本篇我们将介绍在 Sa-Token 中如何通过注解完成权限校验。 Sa-Token 是一个轻量级 java 权限认证框架&#xff0c;主要解决登录认证、权限认证、单点登录、OAuth2、微服务网关鉴权 等一系列权限相关问题。 Gitee 开源地址&#xff1…

生信步骤|EffectorP批量预测病原物效应子

EffectorP软件利用机器学习原理&#xff0c;通过事先收集已知的效应子制备训练集&#xff0c;从而实现病原真菌和卵菌的效应子预测[1]。 EffectorP发展史[2]&#xff1a; 1.0版本最初在16年发表于NEW PHYTOLOGIST&#xff0c;实现了机器学习初步预测效应子。 2.0版本在18年发表…

OPPO官宣:哲库解散,哲库是 OPPO 旗下的芯片厂,类似华为海思的角色,有近 3000 名员工

大家好&#xff0c;我是二哥呀。 这两天&#xff0c;互联网最大的声音之一就是&#xff0c;OPPO 将终止芯片业务&#xff0c;相信大多数小伙伴和二哥一样&#xff0c;第一眼看到这则消息的时候&#xff0c;震惊的同时并惋惜&#xff01; ZEKU 是 OPPO 旗下的芯片厂&#xff0…

Java面试知识点(全)-JVM面试知识点

Java面试知识点(全) 导航&#xff1a; https://nanxiang.blog.csdn.net/article/details/130640392 注&#xff1a;随时更新 JVM内存结构 内存结构 Java虚拟机在运行程序时会把其自动管理的内存划分为以上几个区域&#xff0c;每个区域都有的用途以及创建销毁的时机&#xf…

【JavaScript】手写Promise

&#x1f431; 个人主页&#xff1a;不叫猫先生 &#x1f64b;‍♂️ 作者简介&#xff1a;2022年度博客之星前端领域TOP 2&#xff0c;前端领域优质作者、阿里云专家博主&#xff0c;专注于前端各领域技术&#xff0c;共同学习共同进步&#xff0c;一起加油呀&#xff01; &am…

五. AMS实践,Hook启动未注册的Activity

Activity任务栈解析 正常情况下我们的app中的所有Activity都是运行在同一个任务栈(ActivityStack)里面的,也就是我们app的build.gradle文件中的applicationId那个任务栈. 如何实现Activity运行在不同的任务栈呢? 需要在Intent启动这个Activity的时候,给这个intent赋值,设置代…

【KVM虚拟化】· 存储池、存储卷

目录 &#x1f341;虚拟磁盘文件 &#x1f342;基于文件系统的KVM存储 &#x1f342;基于设备的KVM存储 &#x1f341;使用KVM存储池 &#x1f342;存储池概念 &#x1f341;virsh中存储池命令 &#x1f341;virsh中存储卷命令 &#x1f341;命令实例 &#x1f342;创建存储池 …

一个开源的即时通讯应用 Tailchat

今天给大家介绍一款即时通讯应用&#xff0c;这个开源项目是&#xff1a;Tailchat&#xff0c;它是一个基于 React Typescript 的现代开源 noIM 应用程序。 简单介绍 相信大家都或多或少了解过 Discord / Slack 这样大火的即时通讯应用。两者分别在各自的领域有很大的成就。…