likes
comments
collection
share

Dart 内置类型之 Record,不同于元组!

作者站长头像
站长
· 阅读数 18

[》跳过拾光记忆]

拾光记忆

简介: 该篇主要介绍15 篇文章含有功能的目录,可根据自己的需求选择对应的功能介绍查看。 推荐: ⭐️⭐️⭐️⭐️⭐️

简介: 该篇主要介绍 Flutter 之 IImage 库中如何实现图像反色功能以及实现原理的介绍。 推荐: ⭐️⭐️⭐️⭐️⭐️

简介: 该篇主要介绍 Flutter 之 图形(Canvas) 绘制路径 (Path)基础功能以及方法实现底层代码的解析。 推荐: ⭐️⭐️⭐️⭐️⭐️

简介: 该篇主要介绍 Flutter 中聊天气泡的实现和图像点九图以及在使用图像拉伸实现气泡时遇到问题的分析和解决方法的总结。 推荐: ⭐️⭐️⭐️⭐️⭐️

简介: 该篇主要介绍 YAML的基础信息以及基础语法和对应转化为 JSON 的实例举例。 推荐: ⭐️⭐️⭐️⭐️⭐️

简介: 该篇主要介绍 Dart 中关键字之一的 final,它的特点、应用时机、优点的总结以及应用实例验证和展示。 推荐: ⭐️⭐️⭐️⭐️

简介: 该篇主要介绍 FlutterYAML 文件的各种读取形式以及 YAML 数据的获取。 推荐: ⭐️⭐️⭐️⭐️

简介: 该篇主要介绍 FlutterCompleter 概念和基础方法的介绍以及进阶应用举例。 推荐: ⭐️⭐️⭐️⭐️

[返回拾光记忆《]

一、简介

Record(记录)是匿名的、不可变的聚合类型。与其他集合类型(List、Map)一样,它允许您将多个对象捆绑到一个对象中。与其他集合类型不同的是Record(记录)是固定大小的、异构的和类型化的。

注意: Record 类是所有记录类型的超类型,但它本身并不是任何对象实例的运行时类型,它是一个抽象类(abstract final class Record{...})。 所有实现Record的对象都将记录类型作为其运行时类型。

二、语法

0. 位置字段和命名字段。
  1. 在记录表达式中位置字段是前面没有冒号(:)的对象;命名字段是前面带冒号(:)的对象。如下:

    Dart 内置类型之 Record,不同于元组!
  2. 在声明记录变量时注释中,位置字段在大括号外;命名字段在大括号内,且命名字段要在所有位置字段之后。如下:

    Dart 内置类型之 Record,不同于元组!
1. 记录表达式是以逗号分隔的命名或位置字段列表,括在括号中。
test('Flutter-Record-1', () {
  // 1. 记录表达式是以逗号分隔的命名或位置字段列表,括在括号中。
  var record = ('first', a: 110, {'a': 220}, true);
  print(record.runtimeType);
  // (String, _Map<String, int>, bool, {int a})
});

其中 a:110 中的 a 是命名字段;其他的是位置字段。注意一下 Record 的类型输出变现形式。

2. 记录类型注释是括在括号中的以逗号分隔的类型列表。您可以使用记录类型注释来定义返回类型和参数类型。例如,以下(int, String) 或者 (String, int) 语句是记录类型注释。
test('Flutter-Record-2', () {
  // 2. 记录类型注释是括在括号中的以逗号分隔的类型列表。
  // 您可以使用记录类型注释来定义返回类型和参数类型。
  // 例如,以下(int, String) 或者 (String, int) 语句是记录类型注释。
  (int, String) swapItem((String, int) records) {
    return (records.$2, records.$1);
  }

  print(swapItem(('火警', 119)));
  // 输出: (119, 火警)
});
3. 记录表达式和类型注释中的字段反映了参数和参数在函数中的工作方式。位置字段直接位于括号内
test('Flutter-Record-3', () {
  // 3. 记录表达式和类型注释中的字段反映了参数和参数在函数中的工作方式。位置字段直接位于括号内。
  (int, String) ageAndName;
  ageAndName = (20, '王昭君');
  print(ageAndName);
  // 输出: (20, 王昭君)
});

这是声明一个记录变量,并给定变量中对象的类型以及对象的个数。这可以规范程序后面的赋值情况。

4. 在记录类型注释中,命名字段位于类型和名称对的大括号分隔部分内,位于所有位置字段之后。在记录表达式中,名称位于每个字段值之前,后面带有冒号
// 例1
test('Flutter-Record-4', () {
  // 4. 在记录类型注释中,命名字段位于类型和名称对的大括号分隔部分内,
  // 位于所有位置字段之后。在记录表达式中,名称位于每个字段值之前,后面带有冒号。
  (bool, {int age, String name}) ageAndName;
  ageAndName = (true, age: 18, name: '王昭君');
  print(ageAndName);
});
// 例2
test('Flutter-Record-4-1', () {
  // 4. 在记录类型注释中,命名字段位于类型和名称对的大括号分隔部分内,
  // 位于所有位置字段之后。在记录表达式中,名称位于每个字段值之前,后面带有冒号。
  (int, bool, {int age, String name}) ageAndName;
  ageAndName = (10, true, age: 18, name: '王昭君');
  print(ageAndName);
});
5. 记录类型中命名字段的名称是记录类型定义或其形状的一部分。具有不同名称的命名字段的两条记录具有不同的类型
test('Flutter-Record-5', () {
  // 5. 记录类型中命名字段的名称是记录类型定义或其形状的一部分。
  // `具有不同名称的命名字段的两条记录具有不同的类型`
  ({int age, String name}) ageAndName = (age: 10, name: '王昭君');
  ({int weight, String nick}) weightAndNick = (weight: 10, nick: '王昭君');
  print(ageAndName.runtimeType); // ({int age, String name})
  print(weightAndNick.runtimeType); // ({String nick, int weight})
});

从上面代码输出看两个 Record 对象的 runtimeType 不同。

6. 在记录类型注释中,您还可以命名位置字段,但这些名称纯粹用于文档,不会影响记录的类型。
test('Flutter-Record-6', () {
  // 6. 在记录类型注释中,您还可以命名位置字段,但这些名称纯粹用于文档,不会影响记录的类型。
  (int age, String name) ageAndName = (10, '王昭君');
  (int weight, String nick) weightAndNick = (10, '王昭君');
  print(ageAndName.runtimeType); // (int, String)
  print(weightAndNick.runtimeType); // (int, String)
});

从上面代码输出看两个 Record 对象的 runtimeType 相同。这类似于函数声明或函数 typedef中的位置参数可以具有名称,但这些名称不会影响函数的签名。

三、访问

记录字段可以通过内置的 getter 访问。记录是不可变的,因此字段没有设置器(setter)。 命名字段公开同名的 getter; 位置字段公开 name 的 getter $<position>,跳过命名字段。下面展示访问实例:

test('Flutter-Record-访问', () {
  var infoRecord = ('王昭君', age: 18, sex: true, 1000);
  print(infoRecord.$1); // 王昭君
  print(infoRecord.$2); // 1000
  print(infoRecord.age);// 18
  print(infoRecord.sex);// true
});

从上述代码可知,记录对象的位置字段可以通过 $x 进行获取内容;命名字段通过 命名的name(冒号之前的)进行获取内容。注意: 命名字段不参与位置计算,如下:

Dart 内置类型之 Record,不同于元组!

四、类型

记录中的每个字段都有自己的类型;同一记录中的字段类型可以不同。记录根据其字段的类型进行结构类型化。

  • RecordType - 全位置字段

    // RecordType - 全位置字段
    test('Flutter-Record-类型', () {
        var record = (10, '10.0', null);
        print(record.runtimeType); // (int, String, Null)
    });
    
  • RecordType - 位置和命名字段

    // RecordType - 位置和命名字段
    test('Flutter-Record-类型', () {
        var record = (10, a: '10.0', null, b: 2.0);
        print(record.runtimeType); // (int, Null, {String a, double b})
    });
    
  • RecordType - 全命名字段

    // RecordType - 全命名字段
    test('Flutter-Record-类型', () {
        var record = (a: '10.0', b: 2.0);
        print(record.runtimeType); // ({String a, double b})
    });
    
  • 注意 - 类型补充

    var record = (10, a:10.0, b:'2', true) 的运行时的类型或者声明注解是 (int, bool, {double a, String b}) ,如下所示:

    (int, bool, {double a, String b}) record = (10, a:10.0, b:'2', true);
    print(record.runtimeType) //  (int, bool, {double a, String b})
    

五、应用

常用于在一个方法中返回多个对象。如下:

test('Flutter-Record-应用', () {
  (int, String) getTickInfo() {
    return (10, '郑州');
  }
   
  // 1
  var (count, name) = getTickInfo();
  print(count); // 10
  print(name);  // 郑州
    
  // 2
  var record = getTickInfo();
  print(record.$1); // 10
  print(record.$2); // 郑州
});

Record 的应用非常简单,但是注意一下第一种接受方式。这种接受方式省去变量的创建,相对 List/Map 安全性高。

六、鼓励与支持

上面我们介绍了 Record 的基础知识以及应用。从上面的介绍 Record 很像其他语言中的元组,我们在学习的时候也可以参考以及对比,这样会更深对 Record 的了解。下面是本篇文章的地址仓库 :Flutter之Record的实例地址 欢迎下载和点赞。