跳至主要內容

Dart 語言演進

本頁列出 Dart 程式設計語言的重大變更和新增功能。

若要使用 2.0 之後推出的語言功能,請設定SDK 約束,其版本不得低於 Dart 首次支援該功能的版本。

例如:若要使用 2.12 中推出的空值安全,請在 pubspec.yaml 檔案中將 2.12.0 設定為較低的約束。

yaml
environment:
  sdk: '>=2.12.0 <3.0.0'

每個版本的變更

#

Dart 3.7

#

2025 年 2 月 12 日發布 | Dart 3.7 版本公告

Dart 3.7 在語言中新增了對萬用字元變數的支援。萬用字元變數是名為 _ 的區域變數或參數。萬用字元變數是非綁定的,因此可以宣告多次而不會發生衝突。例如

dart
Foo(_, this._, super._, void _()) {}

從 3.7 版開始,dart format 命令也與語言版本綁定。如果輸入檔案的語言版本為 3.7 或更高版本,則程式碼會以新的高版面樣式格式化。

新樣式看起來與您在引數清單中新增尾隨逗號時取得的樣式類似,但現在格式化工具會為您新增和移除這些逗號。當引數或參數清單分割時,其格式如下

dart
longFunction(
  longArgument,
  anotherLongArgument,
);

您可以在變更日誌中找到更多詳細資訊。

Dart 3.6

#

2024 年 12 月 11 日發布 | Dart 3.6 版本公告

Dart 3.6 在語言中新增了對數字分隔符號底線 (_) 的支援。數字分隔符號提高了長數字常值的可讀性。

dart
var m = 1__000_000__000_000__000_000;

Dart 3.5

#

2024 年 8 月 6 日發布 | Dart 3.5 版本公告

Dart 3.5 沒有新增任何語言功能,但對類型推斷期間考慮的上下文進行了微小的變更。這些包括以下非語言版本化的變更

  • await 運算式的上下文為 dynamic 時,運算式運算元的上下文現在為 FutureOr<_>
  • 當整個 null 條件運算式 (e1 ?? e2) 的上下文為 dynamic 時,e2 的上下文現在為 e1 的靜態類型。

Dart 3.4

#

2024 年 5 月 14 日發布 | Dart 3.4 版本公告

Dart 3.4 對類型分析進行了多項改進。這些包括

  • 條件運算式、null 條件運算式和指派,以及 switch 運算式的類型分析改進。
  • 使 cast 模式的模式上下文類型架構與規格對齊。
  • 使 null 感知展開運算子 (...?) 的類型架構對於 Map 和 Set 常值可為 null,以符合 List 常值的行為。

Dart 3.3

#

2024 年 2 月 15 日發布 | Dart 3.3 版本公告

Dart 3.3 為語言新增了一些增強功能

  • 擴充類型是 Dart 中的一項新功能,允許以零成本包裝現有類型。它們類似於包裝函式類別和擴充方法,但在實作差異和不同的權衡取捨方面有所不同。

    dart
    extension type Meters(int value) {
      String get label => '${value}m';
      Meters operator +(Meters other) => Meters(value + other.value);
    }
    
    void main() {
      var m = Meters(42); // Has type `Meters`.
      var m2 = m + m; // OK, type `Meters`.
      // int i = m; // Compile-time error, wrong type.
      // m.isEven; // Compile-time error, no such member.
      assert(identical(m, m.value)); // Succeeds.
    }
  • 如果沒有衝突的宣告,抽象 Getter 現在可以在私有最終欄位提升的規則下提升。

Dart 3.2

#

2023 年 11 月 15 日發布 | Dart 3.2 版本公告

Dart 3.2 為流程分析新增了增強功能,包括

  • 擴充類型提升以適用於私有最終欄位。先前僅適用於區域變數和參數,現在私有最終欄位可以透過 null 檢查和 is 測試提升為非 null 類型。例如,以下程式碼現在是健全的

    dart
    class Example {
      final int? _privateField;
    
      Example(this._privateField);
    
      void f() {
        if (_privateField != null) {
          // _privateField has now been promoted; you can use it without
          // null checking it.
          int i = _privateField; // OK
        }
      }
    }
    
    // Private field promotions also work from outside of the class:
    void f(Example x) {
      if (x._privateField != null) {
        int i = x._privateField; // OK
      }
    }

    如需私有最終欄位何時可以和何時不能提升的詳細資訊,請查看修正類型提升失敗

  • 修正了if-case 陳述式中類型提升行為的不一致之處,其中要比對的值會擲回例外狀況。

Dart 3.1

#

2023 年 8 月 16 日發布 | Dart 3.1 版本公告

Dart 3.1 沒有新增任何新功能,也沒有對語言進行任何變更。

Dart 3.0

#

2023 年 5 月 10 日發布 | Dart 3.0 版本公告

Dart 3.0 推出了幾項主要的新語言功能

  • 模式,一種新的語法類別,可讓您比對和解構值。
  • 記錄,一種新的類型,可讓您在單一函式傳回中彙總多個不同類型的值。
  • 類別修飾詞,一組新的關鍵字,可讓您控制類別或混合的用法。
  • Switch 運算式,一種新的多向分支形式,允許在預期運算式的地方使用。
  • If-case 子句,一種新的條件建構,可將值與模式比對,並根據模式是否比對來執行 then 或 else 分支。

Dart 3.0 也推出了一些重大語言變更

  • 沒有 mixin 類別修飾詞的類別宣告不再可以作為混合應用。
  • 如果冒號 (:) 用作選用具名參數預設值之前的分隔符號,則現在會出現編譯時間錯誤。請改用等號 (=)。
  • 如果 continue 陳述式目標的標籤未附加到迴圈陳述式 (fordowhile) 或 switch 成員,則現在會出現編譯時間錯誤。

Dart 2.19

#

2023 年 1 月 25 日發布

Dart 2.19 針對類型推斷引入了一些預防措施。這些包括

  • 更多用於無法連線的程式碼案例的流程分析旗標。
  • 不再將無法存取的私有名稱委派給 noSuchMethod
  • 最上層類型推斷會在循環相依性時擲回錯誤。

Dart 2.19 也引入了對未命名程式庫的支援。用於附加程式庫層級文件註解和註釋的程式庫指令可以而且現在應該在沒有名稱的情況下撰寫

dart
/// A really great test library.
@TestOn('browser')
library;

Dart 2.18

#

2022 年 8 月 30 日發布 | Dart 2.18 版本公告

Dart 2.18 增強了類型推斷。此變更允許泛型函式呼叫中引數之間的資訊流動。在 2.18 之前,如果您未在某些方法中指定引數的類型,Dart 會報告錯誤。這些類型錯誤引用了潛在的 null 發生。使用 2.18,編譯器會從調用中的其他值推斷引數類型。您不需要內嵌指定引數類型。

Dart 2.18 也停止支援未擴充 Object 的混合類別。

若要深入瞭解這些功能,請查看

Dart 2.17

#

2022 年 5 月 11 日發布 | Dart 2.17 版本公告

Dart 2.17 使用增強型列舉擴充了列舉功能。增強型列舉允許列舉宣告定義成員,包括欄位、建構子、方法、Getter 等。

Dart 2.17 在建構子中新增了對超級初始化子參數的支援。超級參數可讓您避免必須手動將每個參數傳遞到非重新導向建構子的超級調用中。您可以改用超級參數將參數轉發到超類別建構子。

Dart 2.17 移除了對具名引數的一些限制。具名引數現在可以與位置引數自由交錯。從 Dart 2.17 開始,您可以撰寫以下程式碼

dart
void main() {
  test(skip: true, 'A test description', () {
    // Very long function body here...
  });
}

若要深入瞭解這些功能,請查看

Dart 2.16

#

2022 年 2 月 3 日發布 | Dart 2.16 版本公告

Dart 2.16 沒有為 Dart 語言新增任何新功能。它擴充了 Dart 工具。

Dart 2.15

#

2021 年 12 月 8 日發布 | Dart 2.15 版本公告

Dart 2.15 改進了對函式指標 (稱為撕裂) 的支援。特別是,現在支援建構子撕裂。

Dart 2.14

#

2021 年 9 月 8 日發布 | Dart 2.14 版本公告

Dart 2.14 新增了無符號右移 (或三向右移) 運算子 (>>>)。此新運算子的運作方式與 >> 類似,但它始終以零填滿最高有效位元。

若要深入瞭解這些運算子,請查看位元運算子和移位運算子

Dart 2.14 移除了對類型引數的一些限制。您可以將類型引數傳遞至註釋,並使用泛型函式類型作為類型引數。從 Dart 2.14 開始,您可以撰寫以下程式碼

dart
@TypeHelper<int>(42, "The meaning")
late List<T Function<T>(T)> idFunctions;
var callback = [<T>(T value) => value];
late S Function<S extends T Function<T>(T)>(S) f;

Dart 2.13

#

2021 年 5 月 19 日發布 | Dart 2.13 版本公告

Dart 2.13 擴充了對 類型別名 (typedef) 的支援。類型別名過去僅適用於函式類型,但現在適用於任何類型。您可以在可以使用原始類型的任何地方使用以類型別名建立的新名稱。

Dart 2.13 改進了 Dart FFI 中的結構支援,新增了對內嵌陣列和封裝結構的支援。

Dart 2.12

#

2021 年 3 月 3 日發布 | Dart 2.12 版本公告

Dart 2.12 新增了對 健全的空值安全 的支援。當您選擇加入空值安全時,程式碼中的類型預設為不可為 null,這表示變數不能包含 null,除非您說它們可以。使用空值安全,您的執行階段 null 取消引用錯誤會變成編輯時間分析錯誤。

在 Dart 2.12 中,Dart FFI 從 Beta 版畢業到穩定通道。

Dart 2.10

#

2020 年 10 月 1 日發布 | Dart 2.10 版本公告

Dart 2.10 沒有為 Dart 語言新增任何新功能。

Dart 2.9

#

2020 年 8 月 5 日發布

Dart 2.9 沒有為 Dart 語言新增任何新功能。

Dart 2.8

#

2020 年 5 月 6 日發布 | Dart 2.8 版本公告

Dart 2.8 沒有為 Dart 語言新增任何功能。它確實包含許多準備性的重大變更,以改善空值安全的空值相關可用性和效能。

Dart 2.7

#

2019 年 12 月 11 日發布 | Dart 2.7 版本公告

Dart 2.7 新增了對 擴充方法 的支援,使您能夠為任何類型 (甚至是您無法控制的類型) 新增功能,並具有一般方法呼叫的簡潔性和自動完成體驗。

以下範例使用新的 parseInt() 方法擴充 dart:core 中的 String 類別

dart
extension ParseNumbers on String {
  int parseInt() {
    return int.parse(this);
  }
}

void main() {
  int i = '42'.parseInt();
  print(i);
}

Dart 2.6

#

2019 年 11 月 5 日發布 | Dart 2.6 版本公告

Dart 2.6 引入了一個重大變更 (dart-lang/sdk#37985)。其中 Null 作為 FutureOr<T> 子類型的約束現在會產生 Null 作為 T 的解決方案。

例如:以下程式碼現在會列印 Null。在 Dart 2.6 之前,它會列印 dynamic。匿名閉包 () {} 傳回 Null 類型。

dart
import 'dart:async';

void foo<T>(FutureOr<T> Function() f) { print(T); }

main() { foo(() {}); }

Dart 2.5

#

2019 年 9 月 10 日發布 | Dart 2.5 版本公告

Dart 2.5 沒有為 Dart 語言新增任何功能,但它新增了對使用新的 核心程式庫 dart:ffi 從 Dart 程式碼呼叫原生 C 程式碼 的支援。

Dart 2.4

#

2019 年 6 月 27 日發布

Dart 2.4 引入了一個重大變更 dart-lang/sdk#35097

Dart 現在強制執行超級介面中使用的類型變數的共變性。例如:在此版本之前,Dart 接受但現在拒絕以下程式碼

dart
class A<X> {};
class B<X> extends A<void Function(X)> {};

您現在可以在非同步和產生器函式中使用 async 作為識別碼。

Dart 2.3

#

2019 年 5 月 8 日發布 | Dart 2.3 版本公告

Dart 2.3 新增了三個運算子,旨在改進執行清單操作的程式碼,例如宣告式 UI 程式碼。

展開運算子 可讓您將一個清單中的元素解壓縮到另一個清單中。在以下範例中,buildMainElements() 傳回的清單會解壓縮到傳遞給 children 引數的清單中

dart
Widget build(BuildContext context) {
  return Column(children: [
    Header(),
    ...buildMainElements(),
    Footer(),
  ]);
}

集合 if 運算子可讓您有條件地新增元素。除非應用程式顯示最後一頁,否則以下範例會新增 FlatButton 元素

dart
Widget build(BuildContext context) {
  return Column(children: [
    Text(mainText),
    if (page != pages.last)
      FlatButton(child: Text('Next')),
  ]);
}

集合 for 運算子可讓您建構重複元素。以下範例會為 sections 中的每個區段新增一個 HeadingAction 元素

dart
Widget build(BuildContext context) {
  return Column(children: [
    Text(mainText),
    for (var section in sections)
      HeadingAction(section.heading),
  ]);
}

Dart 2.2

#

2019 年 2 月 26 日發布 | Dart 2.2 版本公告

Dart 2.2 新增了對 Set 常值 的支援

dart
const Set<String> currencies = {'EUR', 'USD', 'JPY'};

Dart 2.1

#

2018 年 11 月 15 日發布 | Dart 2.1 版本公告

Dart 2.1 新增了對 int 轉 double 轉換的支援,允許開發人員使用整數常值設定 double 值。此功能消除了在概念上值為整數時,被迫使用 double 常值 (例如 4.0) 的麻煩。

在以下 Flutter 程式碼中,horizontalvertical 的類型為 double

dart
padding: const EdgeInsets.symmetric(
  horizontal: 4,
  vertical: 8,
)

Dart 2.0

#

2018 年 2 月 22 日發布 | Dart 2.0 版本公告

Dart 2.0 實作了新的 健全類型系統。在 Dart 2.0 之前,類型並非完全健全,而 Dart 非常依賴執行階段類型檢查。Dart 1.x 程式碼必須移轉到 Dart 2。

語言版本控制

#

單一 Dart SDK 可以同時支援多個 Dart 語言版本。編譯器會判斷程式碼的目標版本,並根據該版本解譯程式碼。

當 Dart 引入不相容的功能 (如空值安全) 時,語言版本控制變得重要。當 Dart 引入重大變更時,先前可以編譯的程式碼可能不再編譯。語言版本控制可讓您設定每個程式庫的語言版本以維持相容性。

在空值安全的情況下,Dart SDK 2.12 到 2.19 允許您選擇更新程式碼以使用空值安全。Dart 使用語言版本控制來允許非空值安全程式碼與空值安全程式碼並行執行。此決策啟用了從非空值安全程式碼到空值安全程式碼的移轉。若要檢閱應用程式或套件如何移轉到具有不相容功能的新語言版本的範例,請查看移轉至空值安全

每個套件的預設語言版本都等於 pubspec.yaml 檔案中 SDK 約束的下限

例如:pubspec.yaml 檔案中的以下項目表示此套件預設為 Dart 2.18 語言版本。

yaml
environment:
  sdk: '>=2.18.0 <3.0.0'

語言版本號碼

#

Dart 將其語言版本格式化為以句點分隔的兩個數字。它讀取為主要版本號碼和次要版本號碼。次要版本號碼可能會引入重大變更。

Dart 版本可能會將修補程式號碼附加到語言版本。修補程式不應變更語言,除非是錯誤修正。為了說明:Dart 2.18.3 作為 Dart 2.18 SDK 語言版本的最新版本。

每個 Dart SDK 都支援其主要版本號碼內的所有語言版本。這表示 Dart SDK 2.18.3 支援語言版本 2.0 到 2.18 (含),但不支援 Dart 1.x。

從 SDK 版本衍生語言版本表示以下內容

  • 每當 SDK 的次要版本發布時,都會出現新的語言版本。實際上,許多這些語言版本的運作方式與先前的版本非常相似,並且彼此之間具有完全相容性。例如:Dart 2.9 語言的運作方式與 Dart 2.8 語言非常相似。

  • 當 SDK 的修補程式版本發布時,它無法引入新的語言功能。例如:2.18.3 版本仍然是語言版本 2.18。它必須與 2.18.2、2.18.1 和 2.18.0 保持相容。

每個程式庫的語言版本選擇

#

依預設,套件中的每個 Dart 檔案都使用相同的語言版本。Dart 將預設語言版本識別為 pubspec.yaml 檔案中指定的 SDK 約束下限。有時,Dart 檔案可能需要使用較舊的語言版本。例如,您可能無法同時將套件中的所有檔案移轉到空值安全。

Dart 支援每個程式庫的語言版本選擇。若要選擇使用與套件其餘部分不同的語言版本,Dart 程式庫必須在以下格式中包含註解

dart
// @dart = <major>.<minor>

例如

dart
// Description of what's in this file.
// @dart = 2.17
import 'dart:math';
...

@dart 字串必須在 // 註解中 (而非 ////*),而且它必須出現在檔案中的任何 Dart 程式碼之前。空白字元 (Tab 和空格) 無關緊要,@dart 和版本字串內除外。如先前的範例所示,其他註解可以出現在 @dart 註解之前。

若要瞭解 Dart 團隊如何以及為何開發此版本控制方法,請查看語言版本控制規格