內容

Dart 支援下表中顯示的運算子。此表顯示 Dart 的運算子結合性和 運算子優先順序,從最高到最低,它們是 Dart 運算子關係的近似值。您可以將許多這些 運算子實作為類別成員

說明運算子結合性
一元後置expr++    expr--    ()    []    ?[]    .    ?.    !
一元前置-expr    !expr    ~expr    ++expr    --expr      await expr
乘法*    /    %  ~/
加法+    -
位移<<    >>    >>>
位元 AND&
位元 XOR^
位元 OR|
關係和類型測試>=    >    <=    <    as    is    is!
相等==    !=
邏輯 AND&&
邏輯 OR||
if-null??
條件式expr1    ?    expr2    :    expr3
串接..    ?..
指定=    *=    /=   +=   -=   &=   ^=   
散佈 (請參閱註解)...    ...?

使用運算子時,會建立運算式。以下是運算子運算式的範例

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

運算子優先順序範例

#

運算子表格 中,每個運算子的優先順序都比其後列中的運算子高。例如,乘法運算子 % 的優先順序高於 (並因此在) 等於運算子 == 之前執行,而等於運算子的優先順序又高於邏輯 AND 運算子 &&。此優先順序表示以下兩行程式碼會以相同方式執行

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

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

算術運算子

#

Dart 支援一般算術運算子,如下表所示。

運算子意義
+加法
-減法
-expr一元減法,也稱為否定 (反轉運算式的符號)
*乘法
/除法
~/除法,傳回整數結果
%取得整數除法的餘數 (模數)

範例

dart
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 也支援前置和後置遞增和遞減運算子。

運算子意義
++varvar  =  var + 1 (運算式值為 var + 1)
var++var  =  var + 1 (運算式值為 var)
--varvar  =  var - 1 (運算式值為 var - 1)
var--var  =  var - 1 (運算式值為 var)

範例

dart
int a;
int 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

相等性和關聯運算子

#

下表列出等號和關係運算子的意義。

運算子意義
==相等;請參閱以下討論
!=不相等
>大於
<小於
>=大於或等於
<=小於或等於

若要測試兩個物件 x 和 y 是否代表相同事物,請使用 == 運算子。(在極少數情況下,如果您需要知道兩個物件是否為完全相同的物件,請改用 identical() 函數。)以下是 == 運算子的運作方式

  1. 如果 xy 為 null,則如果兩者都為 null,傳回 true,如果只有一個為 null,傳回 false。

  2. 傳回在 x 上呼叫 == 方法,並帶有引數 y 的結果。(沒錯,像 == 這樣的運算子是呼叫其第一個運算元的函式。有關詳細資訊,請參閱 運算子。)

以下是使用每個相等性和關聯性運算子的範例

dart
assert(2 == 2);
assert(2 != 3);
assert(3 > 2);
assert(2 < 3);
assert(3 >= 3);
assert(2 <= 3);

類型測試運算子

#

asisis! 運算子在執行時期檢查類型時非常方便。

運算子意義
as類型轉換(也用於指定 函式庫前置詞
is如果物件具有指定的類型,則為 True
is!如果物件不具有指定的類型,則為 True

如果 obj 實作 T 指定的介面,則 obj is T 的結果為 true。例如,obj is Object? 永遠為 true。

僅當確定物件為特定類型時,才使用 as 運算子將物件轉換為特定類型。範例

dart
(employee as Person).firstName = 'Bob';

如果您不確定物件是否為類型 T,請使用 is T 在使用物件之前檢查類型。

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

指定運算子

#

正如您所見,您可以使用 = 運算子指定值。如果僅在指定變數為 null 時指定,請使用 ??= 運算子。

dart
// Assign value to a
a = value;
// Assign value to b if b is null; otherwise, b stays the same
b ??= value;

複合指定運算子(例如 +=)會將運算與指定結合在一起。

=*=%=>>>=^=
+=/=<<=&=|=
-=~/=>>=

以下是複合指定運算子的運作方式

複合指定等效表達式
對於運算子 opa op= ba = a op b
範例a += ba = a + b

以下範例使用指定和複合指定運算子

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

邏輯運算子

#

您可以使用邏輯運算子反轉或結合布林表達式。

運算子意義
!expr反轉以下表達式(將 false 變更為 true,反之亦然)
||邏輯 OR
&&邏輯 AND

以下是使用邏輯運算子的範例

dart
if (!done && (col == 0 || col == 3)) {
  // ...Do something...
}

按位元和位移運算子

#

您可以在 Dart 中操作數字的個別位元。通常,您會對整數使用這些位元運算和位移運算子。

運算子意義
&AND
|OR
^XOR
~expr一元位元運算補數(0 變成 1;1 變成 0)
<<向左位移
>>向右位移
>>>無符號向右位移

以下是使用位元和位移運算子的範例

dart
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

// Shift right example that results in different behavior on web
// because the operand value changes when masked to 32 bits:
assert((-value >> 4) == -0x03);

assert((value >>> 4) == 0x02); // Unsigned shift right
assert((-value >>> 4) > 0); // Unsigned shift right

條件式

#

Dart 有兩個運算子,讓你可以簡潔地評估表達式,否則可能需要 if-else 陳述式

條件 ? expr1 : expr2
如果條件為真,則評估expr1(並傳回其值);否則,評估並傳回expr2 的值。
expr1 ?? expr2
如果expr1 為非空值,則傳回其值;否則,評估並傳回expr2 的值。

當你需要根據布林表達式指定值時,請考慮使用條件運算子 ?:

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

如果布林表達式測試為空值,請考慮使用 if-null 運算子 ??(也稱為 null 合併運算子)。

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

前一個範例至少可以用另外兩種方式撰寫,但不會這麼簡潔

dart
// 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';
  }
}

串接符號

#

串接(..?..)允許你對同一個物件進行一系列操作。除了存取實例成員外,你也可以在同一個物件上呼叫實例方法。這通常可以省去建立暫時變數的步驟,並讓你撰寫更流暢的程式碼。

考慮以下程式碼

dart
var paint = Paint()
  ..color = Colors.black
  ..strokeCap = StrokeCap.round
  ..strokeWidth = 5.0;

建構函式 Paint() 傳回 Paint 物件。串接符號之後的程式碼會對此物件進行操作,忽略可能傳回的任何值。

前一個範例等同於以下程式碼

dart
var paint = Paint();
paint.color = Colors.black;
paint.strokeCap = StrokeCap.round;
paint.strokeWidth = 5.0;

如果串接運算的物件可能是空值,則對第一個操作使用null 縮短串接(?..)。從 ?.. 開始保證不會對該空值物件嘗試任何串接操作。

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

前一個程式碼等同於以下程式碼

dart
var button = querySelector('#confirm');
button?.text = 'Confirm';
button?.classes.add('important');
button?.onClick.listen((e) => window.alert('Confirmed!'));
button?.scrollIntoView();

你也可以巢狀串接。例如

dart
final addressBook = (AddressBookBuilder()
      ..name = 'jenny'
      ..email = '[email protected]'
      ..phone = (PhoneNumberBuilder()
            ..number = '415-555-0100'
            ..label = 'home')
          .build())
    .build();

請務必在傳回實際物件的函式上建構串接。例如,以下程式碼會失敗

dart
var sb = StringBuffer();
sb.write('foo')
  ..write('bar'); // Error: method 'write' isn't defined for 'void'.

sb.write() 呼叫傳回 void,而你無法在 void 上建構串接。

散佈運算子

#

散佈運算子評估產生集合的表達式,解開結果值,並將其插入另一個集合中。

散佈運算子實際上不是運算子表達式.../...? 語法是集合文字本身的一部分。因此,你可以在 集合 頁面進一步了解散佈運算子。

由於它不是運算子,因此語法沒有任何「運算子優先順序」。實際上,它具有最低的「優先順序」—任何類型的表達式都可作為散佈目標,例如

dart
[...a + b]

其他運算子

#

你在其他範例中看過大部分剩下的運算子

運算子名稱意義
()函式應用表示函式呼叫
[]下標存取表示呼叫可覆寫的 [] 營運子;範例:fooList[1] 將 int 1 傳遞給 fooList 以存取索引 1 的元素
?[]條件式下標存取類似於 [],但最左邊的運算元可以為 null;範例:fooList?[1] 將 int 1 傳遞給 fooList 以存取索引 1 的元素,除非 fooList 為 null(在此情況下,表達式會評估為 null)
.成員存取參照表達式的屬性;範例:foo.bar 從表達式 foo 中選取屬性 bar
?.條件式成員存取類似於 .,但最左邊的運算元可以為 null;範例:foo?.bar 從表達式 foo 中選取屬性 bar,除非 foo 為 null(在此情況下,foo?.bar 的值為 null)
!非 null 斷言運算子將表達式轉換為其底層的非可為 null 型別,如果轉換失敗則擲回執行時期例外;範例:foo!.bar 斷言 foo 為非 null 並選取屬性 bar,除非 foo 為 null,在此情況下會擲回執行時期例外

如需有關 .?... 運算子的更多資訊,請參閱 類別