<optgroup id="kjtai"><li id="kjtai"><source id="kjtai"></source></li></optgroup><acronym id="kjtai"><sup id="kjtai"></sup></acronym>

    <legend id="kjtai"><i id="kjtai"></i></legend>
    <span id="kjtai"><sup id="kjtai"></sup></span>
    <track id="kjtai"></track>
    1. 一、前言

      Flutter 是 Google 开源的 UI 工具包,帮助开发者通过一套代码库高效构建多平台精美应用,Flutter 开源、免费,拥有宽松的开源协议,支持移动、Web、桌面和嵌入式平台。

      Flutter是使用Dart语言开发的跨平台移动UI框架,通过自建绘制引擎,能高性能、高保真地进行Android和IOS开发。Flutter采用Dart语言进行开发,而并非Java,Javascript这类热门语言,这是Flutter团队对当前热门的10多种语言慎重评估后的选择。因为Dart囊括了多数编程语言的优点,它更符合Flutter构建界面的方式。

      本文主要就是简单梳理一下Dart语言的一些基础知识和语法。关于编程语言的基本语法无外乎那么些内容,注释、变量、数据类型、运算符、流程控制、函数、类、异常、文件、异步、常用库等内容,相信大部分读者都是有一定编程基础的,所以本文就简单地进行一个梳理,不做详细的讲解。大家也可以参考 Dart编程语言中文网

      二、Dart的基本语法

      Dart基本语法是指编写dart代码最基本的一些内容、规范,主要包括注释、变量、数据类型和运算符等内容。

      2.1 注释

      Dart 支持单行注释、多行注释和文档注释。

      • 单行注释:单行注释以 // 开始。 所有在 // 和改行结尾之间的内容被编译器忽略。
        void main() {
          // TODO: refactor into an AbstractLlamaGreetingFactory?
          print('Welcome to my Llama farm!');
        }
      • 多行注释多行注释以  /* 开始, 以 */ 结尾。 所有在 /* 和 */ 之间的内容被编译器忽略 (不会忽略文档注释)。 多行注释可以嵌套。
        void main() {
          /*
           * This is a lot of work. Consider raising chickens.
        
          Llama larry = Llama();
          larry.feed();
          larry.exercise();
          larry.clean();
           */
        }
      • 文档注释:文档注释可以是多行注释,也可以是单行注释, 文档注释以 /// 或者 /** 开始。 在连续行上使用 /// 与多行文档注释具有相同的效果。在文档注释中,除非用中括号括起来,否则Dart 编译器会忽略所有文本。 使用中括号可以引用类、 方法、 字段、 顶级变量、 函数、 和参数。 括号中的符号会在已记录的程序元素的词法域中进行解析。下面是一个引用其他类和成员的文档注释,在生成的文档中,[Food] 会成为一个链接, 指向 Food 类的 API 文档。
        /// A domesticated South American camelid (Lama glama).
        ///
        /// 自从西班牙时代以来,
        /// 安第斯文化就将骆驼当做肉食类和运输类动物。
        class Llama {
          String name;
        
          /// 喂养骆驼 [Food].
          ///
          /// 典型的美洲驼每周吃一捆干草。
          void feed(Food food) {
            // ...
          }
        
          /// 使用 [activity] 训练骆驼
          /// [timeLimit] 分钟。
          void exercise(Activity activity, int timeLimit) {
            // ...
          }
        }

      2.2 变量

      任何保存在变量中的都是一个 对象 , 并且所有的对象都是对应一个  的实例。 无论是数字,函数和 null都是对象。所有对象继承自Object 类。尽管 Dart 是强类型的,但是 Dart 可以推断类型,所以类型注释是可选的。 如果要明确说明不需要任何类型, 需要使用特殊类型 dynamic 。

      2.2.1 创建变量

      var name = 'Bob';

      变量仅存储对象引用,这里的变量是 name 存储了一个 String 类型的对象引用。 “Bob” 是这个 String 类型对象的值。

      name 变量的类型被推断为 String 。 但是也可以通过指定类型的方式,来改变变量类型。 如果对象不限定为单个类型,可以指定为 对象类型 或 动态类型

      //指定为动态类型
      dynamic name = 'Bob';
      //显示指定为字符串类型
      String name = 'Bob';

      2.2.2 默认值

      未初始化的变量默认值是 null。即使变量是数字 类型默认值也是 null,因为在 Dart 中一切都是对象,数字类型 也不例外。

      int lineCount;
      assert(lineCount == null); //结果为true 

      提示: 在生产环境代码中 assert() 函数会被忽略,不会被调用。 在开发过程中, assert(condition) 会在非 true 的条件下抛出异常。

      2.3 常量 Final 和 Const

      使用过程中从来不会被修改的值,我们成为常量,可以使用 final 或 const, 而不是 var 或者其他类型。 Final 变量的值只能被设置一次; Const 变量在编译时就已经固定 (Const 变量 是隐式 Final 的类型.) 。最高级 final 变量或类变量在第一次使用时被初始化。

      提示: 实例变量可以是 final 类型但不能是 const 类型。 必须在构造函数体执行之前初始化 final 实例变量 —— 在变量声明中,参数构造函数中或构造函数的初始化列表中进行初始化。

      2.2.1 常量的创建

      final name = 'Bob'; // Without a type annotation
      final String nickname = 'Bobby';
      //final 不能被修改:
      name = 'Alice'; // Error: 一个 final 变量只能被设置一次。

      如果需要在编译时就固定变量的值,可以使用 const 类型变量。 如果 Const 变量是类级别的,需要标记为 static const。 在这些地方可以使用在编译时就已经固定不变的值,字面量的数字和字符串, 固定的变量,或者是用于计算的固定数字:

      const bar = 1000000; // 压力单位 (dynes/cm2)
      const double atm = 1.01325 * bar; // 标准气压
      
      // Const 关键字不仅可以用于声明常量变量。 还可以用来创建常量值,以及声明创建常量值的构造函数。 任何变量都可以拥有常量值。
      var foo = const [];
      final bar = const []; 
      const baz = []; // 声明 const 的初始化表达式中 const 可以被省略。 比如上面的 baz。  Equivalent to `const []`
      
      //Const 变量的值不可以修改:
      baz = [42]; // Error: 常量变量不能赋值修改。
      
      //非 Final , 非 const 的变量是可以被修改的,即使这些变量 曾经引用过 const 值。
      foo = [1, 2, 3]; // 曾经引用过 const [] 常量值。

      2.2.2 final和const的相同点

      1.声明时必须要赋值

        

      2.只能在初始化赋值一次,之后不能重新赋值

      3.后面都不能接var关键字

      4.类型声明可以忽略,类似 var,可以根据初始化的值推断出变量类型

      2.2.3 final和const的区别

      1、final变量的初始值可以在编译时确定,也可以在运行时确定,cosnt变量的初始值只能是编译时确定的值,比如当前时间

      2.const变量的不可变性是嵌套的,final不是

      const a = {'c': 1};
      a['c'] = 2;
      // 运行结果 Unsupported operation: Cannot set value in unmodifiable Map

      3.内存中的创建:相同的值,final变量会重复创建,const会引用同一份值

        const a = {'c': 1};
        const b = {'c': 1};
        print(a == b);//true
        final c = {'c': 1};
        final d = {'c': 1};
        print(c == d);//false

      2.4 数据类型

      Dart 语言支持以下内建类型:

      • Number:数值类型
      • String:字符串类型
      • Boolean:布尔类型
      • List (也被称为 Array):列表或数组类型
      • Map:字典类型
      • Set:集合类型
      • Rune (用于在字符串中表示 Unicode 字符):
      • Symbol:符号类型

      这些类型都可以被初始化为字面量。 例如, 'this is a string' 是一个字符串的字面量, true 是一个布尔的字面量。因为在 Dart 所有的变量终究是一个对象(一个类的实例), 所以变量可以使用 构造涵数 进行初始化。 一些内建类型拥有自己的构造函数。 例如, 通过 Map() 来构造一个 map 变量。

      2.4.1 Number

      Dart 语言的 Number 有两种类型:

      • int:整数值不大于64位, 具体取决于平台。 在 Dart VM 上, 值的范围从 -263到 263 - 1. Dart 被编译为 JavaScript 时,使用 JavaScript numbers, 值的范围从 -253 到 253 - 1.
      • double:64位(双精度)浮点数,依据 IEEE 754 标准。

      int 和 double 都是 num. 的亚类型。 num 类型包括基本运算 +, -, /, 和 *, 以及 abs() ceil(), 和 floor(), 等函数方法。 (按位运算符,例如?,定义在 int 类中。) 如果 num 及其亚类型找不到你想要的方法, 尝试查找使用 dart:math 库。

      // 整数类型不包含小数点。 下面是定义整数类型字面量的例子:
      var x = 1;
      var hex = 0xDEADBEEF;
      
      // 如果一个数字包含小数点,那么就是小数类型。 下面是定义小数类型字面量的例子: var y = 1.1; var exponents = 1.42e5;
      // 从 Dart 2.1 开始,必要的时候 int 字面量会自动转换成 double 类型。 double z = 1; // 相当于 double z = 1.0. //版本提示: 在dart 2.1 之前,在 double 上下文中使用 int 字面量是错误的。 //以下是将字符串转换为数字的方法,反之亦然: // String -> int var one = int.parse('1'); assert(one == 1); // String -> double var onePointOne = double.parse('1.1'); assert(onePointOne == 1.1); // int -> String String oneAsString = 1.toString(); assert(oneAsString == '1'); // double -> String String piAsString = 3.14159.toStringAsFixed(2); assert(piAsString == '3.14');
      //int 特有的传统按位运算操作,移位(<<, >>),按位与(&)以及 按位或(|)。 例如: assert((3 << 1) == 6); // 0011 << 1 == 0110 assert((3 >> 1) == 1); // 0011 >> 1 == 0001 assert((3 | 4) == 7); // 0011 | 0100 == 0111

      //数字类型字面量是编译时常量。 在算术表达式中,只要参与计算的因子是编译时常量, 那么算术表达式的结果也是编译时常量。 const msPerSecond = 1000; const secondsUntilRetry = 5; const msUntilRetry = secondsUntilRetry * msPerSecond;

      2.4.2 String

      Dart 字符串是一组 UTF-16 单元序列。 字符串通过单引号或者双引号创建。

      var s1 = 'Single quotes work well for string literals.';
      var s2 = "Double quotes work just as well.";
      var s3 = 'It\'s easy to escape the string delimiter.';
      var s4 = "It's even easier to use the other delimiter.";

      字符串可以通过 ${expression} 的方式内嵌表达式。 如果表达式是一个标识符,则 {} 可以省略。 在 Dart 中通过调用就对象的 toString() 方法来得到对象相应的字符串。

      var s = 'string interpolation';
      
      assert('Dart has $s, which is very handy.' ==
          'Dart has string interpolation, ' +
              'which is very handy.');
      assert('That deserves all caps. ' +
              '${s.toUpperCase()} is very handy!' ==
          'That deserves all caps. ' +
              'STRING INTERPOLATION is very handy!');

      提示: == 运算符用来测试两个对象是否相等。 在字符串中,如果两个字符串包含了相同的编码序列,那么这两个字符串相等。

      此外,还有字符串的拼接和多行字符串等用法

      // 用 + 运算符来把多个字符串连接为一个,也可以把多个字面量字符串写在一起来实现字符串连接:
      var s1 = 'String '
          'concatenation'
          " works even over line breaks.";
      assert(s1 ==
          'String concatenation works even over '
          'line breaks.');
      
      var s2 = 'The + operator ' + 'works, as well.';
      assert(s2 == 'The + operator works, as well.'); 
      

      // 使用连续三个单引号或者三个双引号实现多行字符串对象的创建: var s1 = ''' You can create multi-line strings like this one. '''; var s2 = """This is also a multi-line string.""";

      // 使用 r 前缀,可以创建 “原始 raw” 字符串: var s = r"In a raw string, even \n isn't special.";

      **一个编译时常量的字面量字符串中,如果存在插值表达式,表达式内容也是编译时常量, 那么该字符串依旧是编译时常量。 插入的常量值类型可以是 null,数值,字符串或布尔值

      // const 类型数据
      const aConstNum = 0;
      const aConstBool = true;
      const aConstString = 'a constant string';
      
      // 非 const 类型数据
      var aNum = 0;
      var aBool = true;
      var aString = 'a string';
      const aConstList = [1, 2, 3];
      
      const validConstString = '$aConstNum $aConstBool $aConstString'; //const 类型数据
      // const invalidConstString = '$aNum $aBool $aString $aConstList'; //非 const 类型数据,error Not a constant expression.

      2.4.3 Boolean

      Dart 使用 bool 类型表示布尔值。 Dart 只有字面量 true、false 是布尔类型, 这两个对象都是编译时常量。

      Dart 的类型安全意味着不能使用 if (nonbooleanValue) 或者 assert (nonbooleanValue)。 而是应该像下面这样,明确的进行值检查:

      // 检查空字符串。
      var fullName = '';
      assert(fullName.isEmpty);
      
      // 检查 0 值。
      var hitPoints = 0;
      assert(hitPoints <= 0);
      
      // 检查 null 值。
      var unicorn;
      assert(unicorn == null);
      
      // 检查 NaN 。
      var iMeantToDoThis = 0 / 0;
      assert(iMeantToDoThis.isNaN);

      2.4.4 List

      几乎每种编程语言中最常见的集合可能是 array 或有序的对象集合。 在 Dart 中的 Array 就是 List 对象, 通常称之为 List 。 下面是一个 Dart List 的示例:

      var list = [1, 2, 3];

      提示: Dart 推断 list 的类型为 List<int> 。 如果尝试将非整数对象添加到此 List 中, 则分析器或运行时会引发错误。 

      Lists 的下标索引从 0 开始,第一个元素的索引是 0。 list.length - 1 是最后一个元素的索引。 

      var list = [1, 2, 3];
      assert(list.length == 3);
      assert(list[1] == 2);
      
      list[1] = 1;
      assert(list[1] == 1);
      
      //在 List 字面量之前添加 const 关键字,可以定义 List 类型的编译时常量
      var constantList = const [1, 2, 3];
      // constantList[1] = 1; // 取消注释会引起错误。

      List 类型包含了很多 List 的操作函数。 更多信息参考 泛型 和 集合.

      2.4.5 Set

      在 Dart 中 Set 是一个元素唯一且无序的集合。 Dart 为 Set 提供了 Set 字面量和 Set 类型。

      版本提示: 虽然 Set 类型 一直是 Dart 的核心部分, 但在 Dart2.2 中才引入了 Set 字面量 。

      下面是通过字面量创建 Set 的一个简单示例:

      var halogens = {'fluorine', 'chlorine', 'bromine', 'iodine', 'astatine'};

      Note: Dart 推断 halogens 类型为 Set<String> 。如果尝试为它添加一个 错误类型的值,分析器或执行时会抛出错误。

      要创建一个空集,使用前面带有类型参数的 {} ,或者将 {} 赋值给 Set 类型的变量:

      var names = <String>{};
      // Set<String> names = {}; // 这样也是可以的。
      // var names = {}; // 这样会创建一个 Map ,而不是 Set 。

      是 Set 还是 Map ? Map 字面量语法同 Set 字面量语法非常相似。 因为先有的 Map 字母量语法,所以 {} 默认是 Map 类型。   如果忘记在 {} 上注释类型或赋值到一个未声明类型的变量上,   那么 Dart 会创建一个类型为 Map<dynamic, dynamic> 的对象。

      // 使用 add() 或 addAll() 为已有的 Set 添加元素:
      var elements = <String>{};
      elements.add('fluorine');
      elements.addAll(halogens);
      
      // 使用 .length 来获取 Set 中元素的个数:
      var elements = <String>{};
      elements.add('fluorine');
      elements.addAll(halogens);
      assert(elements.length == 5);
      
      // 在 Set 字面量前增加 const ,来创建一个编译时 Set 常量:
      final constantSet = const {
        'fluorine',
        'chlorine',
        'bromine',
        'iodine',
        'astatine',
      };
      // constantSet.add('helium'); // Uncommenting this causes an error.

      更多关于 Set 的内容,参阅 Generic 及 Set

      2.4.6 Map

      通常来说, Map 是用来关联 keys 和 values 的对象。 keys 和 values 可以是任何类型的对象。在一个 Map 对象中一个 key 只能出现一次。 但是 value 可以出现多次。 Dart 中 Map 通过 Map 字面量 和 Map 类型来实现。下面是使用 Map 字面量的两个简单例子:

      var gifts = {
        // Key:    Value
        'first': 'partridge',
        'second': 'turtledoves',
        'fifth': 'golden rings'
      };
      
      var nobleGases = {
        2: 'helium',
        10: 'neon',
        18: 'argon',
      };

      提示: Dart 会将 gifts 的类型推断为 Map<String, String>, nobleGases 的类型推断为 Map<int, String> 。 如果尝试在上面的 map 中添加错误类型,那么分析器或者运行时会引发错误。

      以上 Map 对象也可以使用 Map 构造函数创建:

      var gifts = Map();
      gifts['first'] = 'partridge';
      gifts['second'] = 'turtledoves';
      gifts['fifth'] = 'golden rings';
      
      var nobleGases = Map();
      nobleGases[2] = 'helium';
      nobleGases[10] = 'neon';
      nobleGases[18] = 'argon';

      提示: 这里为什么只有 Map() ,而不是使用 new Map()。 因为在 Dart 2 中,new 关键字是可选的。 

      // 添加 key-value 对到已有的 Map 中:
      var gifts = {'first': 'partridge'};
      gifts['fourth'] = 'calling birds'; // Add a key-value pair
      
      // 从一个 Map 中获取一个 value:
      var gifts = {'first': 'partridge'};
      assert(gifts['first'] == 'partridge');
      
      // 如果 Map 中不包含所要查找的 key,那么 Map 返回 null:
      var gifts = {'first': 'partridge'};
      assert(gifts['fifth'] == null);
      
      // 使用 .length 函数获取当前 Map 中的 key-value 对数量:
      var gifts = {'first': 'partridge'};
      gifts['fourth'] = 'calling birds';
      assert(gifts.length == 2);
      
      // 创建 Map 类型运行时常量,要在 Map 字面量前加上关键字 const。
      final constantMap = const {
        2: 'helium',
        10: 'neon',
        18: 'argon',
      };
      
      // constantMap[2] = 'Helium'; // 取消注释会引起错误。

      更名多关于 Map 的内容,参考 Generics and Maps.

      2.4.7 Rune

      在 Dart 中, Rune 用来表示字符串中的 UTF-32 编码字符

      Unicode 定义了一个全球的书写系统编码, 系统中使用的所有字母,数字和符号都对应唯一的数值编码。 由于 Dart 字符串是一系列 UTF-16 编码单元, 因此要在字符串中表示32位 Unicode 值需要特殊语法支持。

      表示 Unicode 编码的常用方法是, \uXXXX, 这里 XXXX 是一个4位的16进制数。 例如,心形符号 (?) 是 \u2665。 对于特殊的非 4 个数值的情况, 把编码值放到大括号中即可。 例如,emoji 的笑脸 (?) 是 \u{1f600}

      String 类有一些属性可以获得 rune 数据。 属性 codeUnitAt 和 codeUnit 返回16位编码数据。 属性 runes 获取字符串中的 Rune 。

      下面是示例演示了 Rune 、 16-bit code units、 和 32-bit code points 之间的关系。 

      main() {
        var clapping = '\u{1f44f}';
        print(clapping);
        print(clapping.codeUnits);
        print(clapping.runes.toList());
      
        Runes input = new Runes(
            '\u2665  \u{1f605}  \u{1f60e}  \u{1f47b}  \u{1f596}  \u{1f44d}');
        print(new String.fromCharCodes(input));
      }

      提示: 谨慎使用 list 方式操作 Rune 。 这种方法很容易引发崩溃, 具体原因取决于特定的语言,字符集和操作。

      2.4.8 Symbol

      一个 Symbol 对象表示 Dart 程序中声明的运算符或者标识符。 你也许永远都不需要使用 Symbol ,但要按名称引用标识符的 API 时, Symbol 就非常有用了。 因为代码压缩后会改变标识符的名称,但不会改变标识符的符号。 通过字面量 Symbol ,也就是标识符前面添加一个 # 号,来获取标识符的 Symbol 。

      #radix
      #bar

      Symbol 字面量是编译时常量。

      2.5 运算符

      下表是 Dart中定义的运算符,描述的运算符优先级近似于Dart 解析器实际行为。

      描述运算符
      前缀运算符 expr++    expr--    ()    []    .    ?.
      后缀运算符 -expr    !expr    ~expr    ++expr    --expr   
      倍数运算符 *    /    %  ~/
      加减运算符 +    -
      移位运算符 <<    >>    >>>
      位与 &
      位异或 ^
      位或 |
      关系运算符和测试运算符 >=    >    <=    <    as    is    is!
      相等判断 ==    !=   
      逻辑与 &&
      逻辑或 ||
      判空运算符 ??
      条件运算符 expr1 ? expr2 : expr3
      级联运算符 ..
      赋值运算符 =    *=    /=   +=   -=   &=   ^=   etc.

      创建表达式的时候会用到运算符。 下面是一些运算符表达式的实例:

      a++
      a + b
      a = b
      a == b
      c ? a : b
      a is T

      在 运算符表 中, 每一行的运算符优先级,由上到下依次排列,第一行优先级最高,最后一行优先级最低。 例如 %运算符优先级高于 == , 而 == 高于 &&。 根据优先级规则,那么意味着以下两行代码执行的方式相同:

      // 括号可以提高可读性。
      if ((n % i == 0) && (d % i == 0)) ...
      
      // 可读性差,但是是等效的。
      if (n % i == 0 && d % i == 0) ... 

      警告: 对于有两个操作数的运算符,运算符的功能由左边的操作数决定。 例如, 如果有两个操作数 Vector 和 Point, aVector + aPoint 使用的是 Vector 中定义的 + 运算符。

      下面就对dart中的运算符进行常规意义的分类简单列举一下:

      • 算术运算符:+、-、*、/、~/(整除,结果为整数)、%(求余运算)、++(自增)、--(自减)。(++、--分别有前缀和后缀两种表达形式,大家在学习的过程中要注意他们之间的区别)
        assert(2 + 3 == 5);
        assert(2 - 3 == -1);
        assert(2 * 3 == 6);
        assert(5 / 2 == 2.5); // 结果是双浮点型
        assert(5 ~/ 2 == 2); // 结果是整型
        assert(5 % 2 == 1); // 余数
        
        assert('5/2 = ${5 ~/ 2} r ${5 % 2}' == '5/2 = 2 r 1');
      • 关系运算符:==、!=、>、<、>=、<=,都是常规符号,不做其他解释,大家要注意的是关系运算符的表达式结果为boolean类型。
        assert(2 == 2);
        assert(2 != 3);
        assert(3 > 2);
        assert(2 < 3);
        assert(3 >= 3);
        assert(2 <= 3);
      • 逻辑运算符:&&(逻辑与,短路运算)、||(逻辑或,短路运算)、!。
        //短路运算,即当左边的表达式结果能确定最终结果时,右边的表达式不再进行运算
          var a = 10;
          var b = a > 9 || a++ > 10; //a>9成立,又是或运算,所以b的结果为true,右边的 a++ > 10不会进行计算,所以a的值不会加1
          print(a); //10
      • 赋值运算符:=、+=、-=、*=、/=。。。等一系列的扩展赋值运算符
        var a = 2; // 使用 = 复制
        a *= 3; // 复制并做乘法运算: a = a * 3
        assert(a == 6);
      • 位运算符:&(按位与运算)、|(按位或运算)、^(按位异或运算)、<<(按位左移)、>>(按位右移)。(所有的位运算都是以二进制形式进行的)
        final value = 0x22;
        final bitmask = 0x0f;
        
        assert((value & bitmask) == 0x02); // AND
        assert((value & ~bitmask) == 0x20); // AND NOT
        assert((value | bitmask) == 0x2f); // OR
        assert((value ^ bitmask) == 0x2d); // XOR
        assert((value << 4) == 0x220); // Shift left
        assert((value >> 4) == 0x02); // Shift right
      • 条件运算符:
        •  condition ? expr1 : expr2 如果条件为 true, 执行 expr1 (并返回它的值), 否则, 执行并返回 expr2 的值。
        •  expr1 ?? expr2 如果 expr1 是 non-null, 返回 expr1 的值; 否则, 执行并返回 expr2 的值。
      • 级联运算符(..):可以实现对同一个对像进行一系列的操作。 除了调用函数, 还可以访问同一对象上的字段属性。 这通常可以节省创建临时变量的步骤, 同时编写出更流畅的代码。严格的来讲, “两个点” 的级联语法不是一个运算符。 它只是一个 Dart 的特殊语法。
        // 第一句调用函数 querySelector() , 返回获取到的对象。 获取的对象依次执行级联运算符后面的代码, 代码执行后的返回值会被忽略。
        querySelector('#confirm') // 获取对象。
          ..text = 'Confirm' // 调用成员变量。
          ..classes.add('important')
          ..onClick.listen((e) => window.alert('Confirmed!'));
        
        // 上面的代码等价于:
        var button = querySelector('#confirm');
        button.text = 'Confirm';
        button.classes.add('important');
        button.onClick.listen((e) => window.alert('Confirmed!'));
        
        // 级联运算符可以嵌套,例如:
        final addressBook = (AddressBookBuilder()
              ..name = 'jenny'
              ..email = 'jenny@example.com'
              ..phone = (PhoneNumberBuilder()
                    ..number = '415-555-0100'
                    ..label = 'home')
                  .build())
            .build();
        
        // 在返回对象的函数中谨慎使用级联操作符。 例如,下面的代码是错误的:
        var sb = StringBuffer();
        sb.write('foo')
          ..write('bar'); // Error: 'void' 没哟定义 'write' 函数。
        // sb.write() 函数调用返回 void, 不能在 void 对象上创建级联操作。
      • 类型判定运算符:as()、is(判定是否是指定类型或该类型子类的对象)、is! (跟is相反)。
        • 使用 as 运算符将对象强制转换为特定类型。 通常,可以认为是 is 类型判定后,被判定对象调用函数的一种缩写形式。 请考虑以下代码: 
      if (emp is Person) {
        // 类型判断
        // emp.firstName = 'Bob';
      
        // 下面这种写法一般是没问题的,进行类型强转
        (emp as Person).firstName = 'Bob';
      }

       

       

      posted on 2021-02-01 15:58  mukekeheart  阅读(89)  评论(0编辑  收藏

      手机购彩 打竹板顺口溜 | 哪吒之魔童降世顺口溜 | 骂人语音半个小时录音 | 没事爱上我做什么 | 怎么诅咒一个人快点死 | 相师类小说排行榜 | 骂人录音大全mp3 | 郭靖来到桃花岛 | 亚伯勒 | 痋术 | 金丝熊寿命 | 南非诞生双脸小猫 | 宇宙会不会是一个骗局 | 卢本伟骂人脏话全集 | 中国刑侦十大悍匪电视剧 | 合肥话 | 撩汉套路情话聊天记录 | battle什么意思 | 中银大厦闹鬼事件21楼 | 琼瑶 反击 |