Dart 简明教程 - 03 - Operators

1,119 阅读5分钟

本系列教程大多翻译自 Dart 官网,因本人英语水平有限,可能有些地方翻译不准确,还请各位大佬斧正。如需转载请标明出处,谢绝 CSDN 爬虫党。

Operators 运算符

下面的表格是 Dart 默认的运算符,不过你可以重写大部分运算符,具体可看官网的 Overridable operators

Description Operator
一元后缀运算符 expr++ expr-- () [] . ?.
一元前缀运算符 -expr !expr ~expr ++expr --expr
倍数运算符 * / % ~/
加法运算符 + -
位数运算符 << >> >>>
按位与 &
按位异或 ^
按位或 |
关系&类型比较运算符 >= > <= < as is is!
相等运算符 == !=
逻辑与 &&
逻辑或 ||
判断 null ??
三目运算符 expr1 ? expr2 : expr3
联级操作符 ..
组合运算符 = *= /= += -= &= ^= 等等

上述表格的运算优先级按从高到低排列。

比如,%的比==优先级高,而==又比&&高,下面两个表达式是相等的:

// Parentheses improve readability.
if ((n % i == 0) && (d % i == 0)) ...

// Harder to read, but equivalent.
if (n % i == 0 && d % i == 0) ...

当你使用运算符的时候,就相当于创建了一个表达式:

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

算数运算符(Arithmetic operators)

Operator Meaning
+ 加法
- 减法
-expr 一元减法、取反
* 乘法
/ 除法
~/ 整除
% 取模运算
assert(2 + 3 == 5);
assert(2 - 3 == -1);
assert(2 * 3 == 6);
assert(5 / 2 == 2.5); // Result is a double
assert(5 ~/ 2 == 2); // Result is an int
assert(5 % 2 == 1); // Remainder

assert('5/2 = ${5 ~/ 2} r ${5 % 2}' == '5/2 = 2 r 1');

Dart 还支持前缀、后缀运算符

Operator Meaning
++var var = var + 1 (expression value is var + 1)
var++ var = var + 1 (expression value is var)
--var var = var - 1 (expression value is var – 1)
var-- var = var - 1 (expression value is var)
var a, b;

a = 0;
b = ++a; // Increment a before b gets its value.
assert(a == b); // 1 == 1

a = 0;
b = a++; // Increment a AFTER b gets its value.
assert(a != b); // 1 != 0

a = 0;
b = --a; // Decrement a before b gets its value.
assert(a == b); // -1 == -1

a = 0;
b = a--; // Decrement a AFTER b gets its value.
assert(a != b); // -1 != 0

关系运算符(Equality and relational operators)

Operator Meaning
== 相等
!= 不等
> 大于
< 小于
>= 大于或等于
<= 小于或等于

要判断两个对象 x 和 y 是否相等,使用 ==。(要判断两个对象是否是同一个对象,使用 identical() 方法。

这是 == 的判断逻辑

  1. 如果 x 和 y 都为 null,返回 true;其中一个为 null,返回 false;
  2. 返回调用 x.==(y) 的结果。
assert(2 == 2);
assert(2 != 3);
assert(3 > 2);
assert(2 < 3);
assert(3 >= 3);
assert(2 <= 3);

类型判断符(Type test operators)

Operator Meaning
as Typecast (also used to specify library prefixes)
is True if the object has the specified type
is! False if the object has the specified type

obj is T 为 true 的情况是, objT 实例化的结果。例如,obj is Object 永远为 true

使用 as 运算符去判断 object 是否是一个指定的类型。通常,你应该简略的编写表达式。比如:

if (emp is Person) {
  // Type check
  emp.firstName = 'Bob';
}

你可以让代码更简洁:

(emp as Person).firstName = 'Bob';

Note: 两段代码相等,如果 empnull 或不是 Person 类,第一个例子中(is)什么都不做,第二个例子(as)会抛出异常。

赋值运算符(Assignment operators)

// Assign value to a
a = value;
// Assign value to b if b is null; otherwise, b stays the same
b ??= value; // 在 JavaScript 中相当于 b = b === null ? value : b;

还有其他结合的赋值运算符

= –= /= %= >>= ^=
+= *= ~/= &= <== !=

例如:

var a = 2; // Assign using =
a *= 3; // Assign and multiply: a = a * 3
assert(a == 6);

逻辑运算符(Logical operators)

Operator Meaning
!expr 逻辑取反
|| 逻辑或
&& 逻辑与
if (!done && (col == 0 || col == 3)) {
  // ...Do something...
}

位操作和位移运算符(Bitwise and shift operators)

你可以在 Dart 中对数字进行位移操作,通常操作的是整数。

Operator Meaning
&
|
^ 异或
~expr 二进制取反
<< 左移
>> 右移
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

条件表达式(Conditional expressions)

Dart 有两种运算符可以让你更简洁的表达 if-else 语句。

condition ? expr1 : expr2

如果 condition 为 true, 执行 expr1 (并且返回它的值),否则,执行 expr2

expr1 ?? expr2

如果 expr1null,返回它的值,否则,执行并返回 expr2 的值。

但你基于一个布尔值来赋值的话,可以考虑使用?:

var visibility = isPublic ? 'public' : 'private';

如果判断布尔表达式为null,考虑使用??

String playerName(String name) => name ?? 'Guest';

上面的例子还有两种写法,但是不够简洁:

// Slightly longer version uses ?: operator.
String playerName(String name) => name != null ? name : 'Guest';

// Very long version uses if-else statement.
String playerName(String name) {
  if (name != null) {
    return name;
  } else {
    return 'Guest';
  }
}

联级操作符(Cascade notation)

联级操作符(..)允许你对同一个对象执行一系列操作。在函数调用的时候,你可以在同一个对象上访问字段,它会存储每一步创建的临时变量,以便于你编写流水式代码:

querySelector('#confirm') // Get an object.
  ..text = 'Confirm' // Use its members.
  ..classes.add('important')
  ..onClick.listen((e) => window.alert('Confirmed!'));

第一个方法调用,即querySelector(),返回一个选择器对象。然后连着联级操作符的选择器对象,会忽略任何后续的可能的返回值。

上述例子类似于:

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: method 'write' isn't defined for 'void'.

因为 sb.write() 返回的是 void,你不能对 void 使用联级操作符。

Note: 特别说明,联级操作符的双点(..)号并不是个运算符,只是 Dart 语法的一部分。

其他操作符

Operator Name Meaning
() Function application 调用函数
[] List access 调用数组下标对应的值
. Member access 调用表达式的属性
?. Conditional member access .差不多,但是可以处理符号左边为null的情况,比如foo?.bar,当foo不为null时,选择bar属性(如果foonullfoo?.bar的值为null)

更多关于 .,?...的信息,请见Classes

系列文章:

Dart 简明教程 - 01 - Concepts & Variables
Dart 简明教程 - 02 - Functions
Dart 简明教程 - 03 - Operators
Dart 简明教程 - 04 - Control flow statements
Dart 简明教程 - 05 - Exceptions
Dart 简明教程 - 06 - Classes
Dart 简明教程 - 07 - Generics
Dart 简明教程 - 08 - Libraries and visibility
Dart 简明教程 - 09 - Asynchrony support
Dart 简明教程 - 10 - Generators & Isolates & Typedefs & Metadata...