內容

Dart 語言演變

此頁面列出了 Dart 程式語言的重大更改和新增內容。

要使用 2.0 之後引入的語言功能,請設定一個 SDK 約束,該約束不低於 Dart 首次支援該功能的版本。

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

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

每個版本的更改

#

Dart 3.5

#

2024 年 8 月 6 日釋出 | Dart 3.5 公告

Dart 3.5 沒有新增新的語言功能,但在型別推斷期間考慮的上下文中做了一些小的更改。這些包括以下非語言版本化的更改

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

Dart 3.4

#

2024 年 5 月 14 日釋出 | Dart 3.4 公告

Dart 3.4 在型別分析方面做了幾個改進。這些包括

  • 改進對條件表示式、if-null 表示式和賦值以及 switch 表示式的型別分析。
  • 使強制轉換模式的模式上下文型別模式與規範保持一致。
  • 使空感知擴充套件運算子 (...?) 的型別模式對於對映和集合字面量可為空,以匹配列表字面量的行為。

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.
    }
  • 如果不存在衝突的宣告,現在抽象獲取器可以在 私有 final 欄位提升 的規則下進行提升。

Dart 3.2

#

2023 年 11 月 15 日釋出 | Dart 3.2 公告

Dart 3.2 對流分析添加了增強功能,包括

  • 擴充套件了 型別提升 以適用於私有 final 欄位。以前僅適用於區域性變數和引數,現在私有 final 欄位可以透過空檢查和 is 測試提升為非空型別。例如,以下程式碼現在是健全的

    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
      }
    }

    有關私有 final 欄位何時可以和不可提升的更多資訊,請檢視 修復型別提升失敗

  • 糾正了 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 會報告錯誤。這些型別錯誤引用了潛在的空值出現。在 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 添加了對健全的空安全的支援。當您選擇加入空安全時,程式碼中的型別預設情況下為非空,這意味著變數不能包含空值,除非您說它們可以。使用空安全,您的執行時空指標取消引用錯誤將變成編輯時分析錯誤。

在 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:coreString

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 程式碼呼叫本機 C 程式碼的支援,使用新的核心庫 dart:ffi

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 添加了對集合文字的支援

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 程式碼之前。空格(製表符和空格)無關緊要,除非在 @dart 和版本字串中。如前面的示例所示,其他註釋可以出現在 @dart 註釋之前。

要了解 Dart 團隊如何以及為何開發此版本控制方法,請檢視語言版本控制規範