美文网首页Dart
善用 Dart 运算符编写简洁无错的代码

善用 Dart 运算符编写简洁无错的代码

作者: 全站工程师 | 来源:发表于2019-03-26 12:56 被阅读8次

    此文是致力于帮助你更好地理解并高效使用 Dart 语言系列文集的第一篇。

    Dart(2.0+) 和 Flutter 都是相对较新的技术,每天都有大量的人加入开发者社区,他们参考的很多示例代码仍在照搬其他语言中的代码模式,而未使用 Dart 提供的完整运算符集。

    1、 ?:(三目运算符)

    三目运算符已经存在于许多语言中,它允许将 if-else 语句中两条可能的执行路径改写为更简洁的形式。

    比如以下代码:

    可以写成:

    三元运算符的结构如下所示:

    condition ? (statement if true) : (statement if false);

    如果涉及到返回值,return只需要加在开头,而不是在子语句中:

    return condition ? (statement if true) : (statement if false);

    而不是

    condition ? return (statement if true) : return (statement if false);

    2、 ??

    ?? 是 null 检查符。在上例中,如果 person.name 为 null,则 name 被赋值为 "John Doe"。这大大简化了代码,减少了先检查 name 是否为空,再决定如何赋值的逻辑(如下图的代码对比)。

    ?? 运算符无需大量检查代码,能更加容易地处理意外的 null 值。

    3、?.

    设想一个叫 Point 的类,它有 x 和 y 成员:

    classPoint {
    int x;
    int y;
    Point(this.x, this.y);
    }

    如果我们有一个未初始化的 Point 对象,并且试图访问内部成员,它不会返回 null,而是直接抛出一个错误。

    比如:

    
    Point point;
    
    print(point.x);
    
    

    将抛出:

    Unhandled exception:
    NoSuchMethodError: The getter 'x'was called on null.
    Receiver: null
    Tried calling: x

    相反,如果它只返回 null,我们可以就很容易地处理和解决未初始化的问题。

    同样,简单的解决方案是使用 if-else:

    这看起来不错,但很容易遇到限制。以我们解析 JSON 为例,它可能有很多层嵌套的数据。比如:

    pages[0].contributors[0].authorDetails.basicInfo.firstName

    程序中任何错误都可能导致这个调用链中某个部分为 null。例如说,authorDetails 可能根本没有 basicInfo 字段。

    在这些情况下,判空检查是一场噩梦,只要这些字段中的一个字段为空(firstName 除外,因为它是最后一个字段),则整个调用都会失败。

    那我们该怎么办?没有简单的 if-else 或三目运算解决方案。而且在一个完美的系统里,这个错误根本不应该存在,但我们并不总会有完美的系统和 API。此时,?. 运算符派上用场了。

    这个运算符大致表述为:“如果对象不为 null,则访问内部字段,否则返回 null。”

    因此,即使我们前面的 point.x 示例也会抛出 null 而不是错误。这使我们的工作变得更加容易,并且可以简单地使用上一个运算符来处理 null 错误。

    这里如果 point 未初始化,访问 x 将返回 null 而不是抛出错误。然后这个 null 被 null 检查运算符(??)捕获,该运算符将 0 赋值给变量 x。

    类似地,我们可以将前面的示例修改为:

    pages[0]?.contributors[0]?.authorDetails?.basicInfo?.firstName ?? "N/A";

    现在,如果表达式任意部分为 null,则将返回 "N/A"。

    4、??=

    ??= 可简单的理解为:“如果表达式左侧为空,则执行赋值”。即只有当变量为 null 时才会被赋值。

    可以避免给变量做不必要的重新赋值。

    5、=>

    => 在 Dart 中被称为胖箭头 (fat arrow) 符号。它有两种不同的用途,两者都与定义函数有关。

    首先将其作为返回某物的简写,=> x 表示 { return x;}

    此外该运算符也适用于单个语句,即使不返回任何内容。

    请注意,如果返回类型是 void,则即使是 => s 也不会返回任何东西。

    6、..(级联符号)

    级联表示法是一种修改对象属性的简单方式,通常用于在创建对象而不是获取该对象的引用时逐个修改其属性。

    我们要举的第一个例子还是之前的 Point 类。假设我们首先需要初始化类,然后设置x和y属性。你可能会想到这么做:

    Point p = Point();
    p.x= 3;
    p.y= 6;

    级联表示法为我们提供了一种更简单的方法,无需再次使用对象来设置属性。

    需要注意的,如果我们只是使用 . 运算符,第一行不会返回一个 Point 对象。

    级联符号的主要作用是:

    1. 将 Point 对象创建为默认值;

    2. 通过级联操作更改任何受影响的属性;

    3. 返回原始对象(此处为 Point 实例);

    这在需要设置大量属性时非常有用,例如在 Builder 模式中。Dart 文档中有个很好的例子:

    7、~/

    Dart 也有几个用于加速算术运算的运算符。~/ 运算符返回除法计算结果的整数部分。

    以上介绍的这些运算符简化了代码并减少了 Bug 的发生。

    8、追加:展开运算符 ...(尚未发布)

    ... 是一个还在讨论中的运算符,用作 Dart 中集合 (collections) 的展开运算符。

    List 可以很方便地被展开:

    这段代码直接将 demoList 的元素展开添加至列表中,而不是将其作为 List 对象添加。


    来源:https://medium.com/flutter-community/simple-and-bug-free-code-with-dart-operators-2e81211cecfe
    作者:Deven Joshi
    编译:码王爷

    相关文章

      网友评论

        本文标题:善用 Dart 运算符编写简洁无错的代码

        本文链接:https://www.haomeiwen.com/subject/lnruhxtx.html