目錄

Dart 3 移轉指南

Dart 3 是個重大版本,為 Dart 引入了新的核心功能:記錄模式類別修改器

除了這些新功能之外,Dart 3 還包含許多可能會中斷現有程式碼的變更。

本指南將協助您在升級到 Dart 3後解決您可能會遇到的任何遷移問題。

簡介

#

未設定版本和已設定版本變更

#

下列列出的可能中斷變更屬於兩個類別之一

  • 未設定版本變更:這些變更會影響在升級到 Dart 3.0 SDK 或更新版本後的所有 Dart 程式碼。沒有辦法「關閉」這些變更。

  • 已設定版本變更:這些變更僅適用於套件或應用程式的語言版本設定為 >= Dart 3.0 時。 語言版本來自 pubspec.yaml 檔案 中的 sdk 下限約束。像這樣的 SDK 約束不會套用 Dart 3 已設定版本變更

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

    但像這樣的 SDK 約束會套用

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

若要使用新的 Dart 3 功能,您必須將語言版本更新為 3.0。這會讓您同時取得 Dart 3 已設定版本變更。

Dart 3 向下相容性

#

許多在 Dart 2.12 或更新版本中使用空安全性的套件和應用程式很可能與 Dart 3 向後相容。對於任何下限約束為 SDK 2.12.0 或更高版本的套件而言,這都是可行的。

Dart 的 pub 工具允許解析,即使上限約束限制在低於 3.0.0 的版本時也是如此。例如,具有下列約束的套件將被允許使用 Dart 3.x SDK 解析,因為當下限約束為 2.12 或更高版本時,pub 會將上限約束 <3.0.0 重新詮釋為 <4.0.0

yaml
environment:
  sdk: '>=2.14.0 <3.0.0'           # This is interpreted as '>=2.14.0 <4.0.0'

這允許開發人員在已經支援 2.12 空安全性的套件中使用 Dart 3 穩定的空安全性,而不需要第二次遷移,除非程式碼受到任何其他 Dart 3 變更影響。

測試影響

#

若要了解您的原始碼是否受到任何 Dart 3 變更影響,請使用下列步驟

$ dart --version    # Make sure this reports 3.0.0 or higher.
$ dart pub get      # This should resolve without issues.
$ dart analyze      # This should pass without errors.

如果 pub get 步驟失敗,請嘗試升級您的相依性,看看較新的版本是否支援 Dart 3

$ dart pub upgrade
$ dart analyze      # This should pass without errors.

或者,如果需要,也包含 主要版本 升級

$ dart pub upgrade --major-versions
$ dart analyze      # This should pass without errors.

Dart 3 語言變更

#

100% 穩健的 Null 安全

#

Dart 2.12 在兩年前多引入了 Null 安全性。在 Dart 2.12 中,使用者需要啟用 Null 安全性 使用 pubspec 設定。在 Dart 3 中,Null 安全性是內建的;您無法關閉它。

範圍

#

這是一個 未設定版本 變更,適用於所有 Dart 3 程式碼。

症狀

#

未支援 Null 安全性所開發的套件,在使用 pub get 解決相依性時,將會造成問題

$ dart pub get

Because pkg1 doesn't support null safety, version solving failed.
The lower bound of "sdk: '>=2.9.0 <3.0.0'" must be 2.12.0 or higher to enable null safety.

使用 語言版本註解 選擇低於 2.12 的任何語言版本,而選擇退出 Null 安全性的函式庫,將會造成分析或編譯錯誤

$ dart analyze .
Analyzing ....                         0.6s

  error • lib/pkg1.dart:1:1 • The language version must be >=2.12.0. 
  Try removing the language version override and migrating the code.
  • illegal_language_version_override
$ dart run bin/my_app.dart
../pkg1/lib/pkg1.dart:1:1: Error: Library doesn't support null safety.
// @dart=2.9
^^^^^^^^^^^^

遷移

#

在開始任何至 Dart 3 的遷移之前,請確保您的應用程式或套件已 100% 遷移至啟用 Null 安全性。這需要 Dart 2.19 SDK,而不是 Dart 3 SDK。若要了解如何先將您的應用程式或套件遷移至支援 Null 安全性,請查看 Null 安全性遷移指南

預設值冒號語法

#

基於歷史原因,已命名選用參數可以使用 := 指定其預設值。在 Dart 3 中,只允許使用 = 語法。

範圍

#

這是一個 已設定版本 變更,僅適用於語言版本 3.0 或更新版本。

症狀

#

Dart 分析產生類似這樣的錯誤

line 2 • Using a colon as a separator before a default value is no longer supported.

遷移

#

從使用冒號變更為

dart
int someInt({int x: 0}) => x;

使用等號

dart
int someInt({int x = 0}) => x;

此遷移可以手動進行,或使用 dart fix 自動進行

$ dart fix --apply --code=obsolete_colon_for_default_value

mixin

#

在 Dart 3 之前,任何 class 都可以使用作 mixin,只要它沒有宣告的建構函式,且除了 Object 之外沒有超類別。

在 Dart 3 中,在語言版本 3.0 或更新版本中函式庫中宣告的類別,除非標記為 mixin,否則無法用作 mixin。此限制適用於嘗試將類別用作 mixin 的任何函式庫中的程式碼,無論後者的函式庫語言版本為何。

範圍

#

這是一個 已設定版本 變更,僅適用於語言版本 3.0 或更新版本。

症狀

#

類似這樣的分析錯誤

Mixin can only be applied to class.

當在 with 子句中使用既不是 mixin class 也不是 mixin 的類別時,分析器會產生此診斷。

遷移

#

判斷類別是否打算用作混合。

如果類別定義介面,請考慮使用 implements

switch

#

Dart 3.0 將 switch 案例解釋為 模式,而不是常數表達式。

範圍

#

這是一個 已設定版本 變更,僅適用於語言版本 3.0 或更新版本。

症狀

#

在 switch 案例中找到的大多數常數表達式都是具有相同含義的有效模式(命名常數、文字等)。這些將表現相同,並且不會出現任何症狀。

少數無效模式的常數表達式將觸發 invalid_case_patterns 程式碼檢查

遷移

#

您可以透過在案例模式前加上 const 來還原為原始行為,因此它不再被解釋為模式

dart
case const [1, 2]:
case const {'k': 'v'}:
case const {1, 2}:
case const Point(1, 2):

您可以使用 dart fix 或透過您的 IDE 來快速修復這個重大變更。

continue

#

如果 continue 陳述式針對的標籤不是迴圈(fordowhile 陳述式)或 switch 成員,Dart 3 會報告編譯時間錯誤。

範圍

#

這是一個 已設定版本 變更,僅適用於語言版本 3.0 或更新版本。

症狀

#

您會看到類似這樣的錯誤

The label used in a 'continue' statement must be defined on either a loop or a switch member.

遷移

#

如果可以接受變更行為,請變更 continue 以針對有效的標籤陳述式,該陳述式必須附加到 fordowhile 陳述式。

如果您要保留行為,請將 continue 陳述式變更為 break 陳述式。在 Dart 的先前版本中,未針對迴圈或 switch 成員的 continue 陳述式表現得像 break

Dart 3 核心函式庫變更

#

已移除 API

#

重大變更 #49529:核心函式庫已清理,以移除已棄用多年的 API。下列 API 不再存在於 Dart 核心函式庫中。

範圍

#

這是一個 未設定版本 變更,適用於所有 Dart 3 程式碼。

dart:core

#
  • 移除已棄用的 List 建構函式,因為它不是 Null 安全的。使用清單文字(例如 [] 表示空清單或 <int>[] 表示空的類型化清單)或 List.filled。這只會影響非 Null 安全的程式碼,因為 Null 安全的程式碼已經無法使用這個建構函式。
  • 移除 int.parsedouble.parsenum.parse 上已棄用的 onError 參數。改用 tryParse 方法。
  • 移除已棄用的 proxyProvisional 註解。原始的 proxy 註解在 Dart 2 中沒有作用,而 Provisional 類型和 provisional 常數僅在 Dart 2.0 開發過程中內部使用。
  • 移除已棄用的 Deprecated.expires getter。改用 Deprecated.message
  • 已移除已棄用的 CastError 錯誤。請改用 TypeError
  • 已移除已棄用的 FallThroughError 錯誤。先前會引發此錯誤的穿透類型,已在 Dart 2.0 中改為編譯時期錯誤。
  • 已移除已棄用的 NullThrownError 錯誤。此錯誤絕不會從 Null 安全程式碼中引發。
  • 已移除已棄用的 AbstractClassInstantiationError 錯誤。在 Dart 2.0 中,呼叫抽象類別的建構函式已改為編譯時期錯誤。
  • 已移除已棄用的 CyclicInitializationError。在 Null 安全程式碼中,不再在執行時期偵測到循環相依性。此類程式碼反而會以其他方式失敗,可能會出現 StackOverflowError。
  • 已移除已棄用的 NoSuchMethodError 預設建構函式。請改用 NoSuchMethodError.withInvocation 命名建構函式。
  • 已移除已棄用的 BidirectionalIterator 類別。現有的雙向迭代器仍然可以使用,只是它們沒有共用超類型將它們鎖定到特定名稱,以進行後退移動。

dart:async

#

dart:developer

#

dart:html

#
  • 如先前公告,已移除 DocumentHtmlDocument 中已棄用的 registerElementregisterElement2 方法。詳情請參閱 #49536

dart:math

#
  • Random 介面只能實作,不能延伸。

dart:io

#
  • 更新 NetworkProfiling 以容納 vm_service:11.0.0 中引入的新 String id

症狀

#

Dart 分析(例如在您的 IDE 中,或在 dart analyze/flutter analyze 中)將會失敗,並出現類似下列錯誤訊息:

error line 2 • Undefined class 'CyclicInitializationError'.

遷移

#

手動從使用這些 API 中遷移。

Extends 和 implements

#

Dart 3 支援新的 類別修改子,可以限制類別的功能。它們已套用至核心函式庫中的多個類別。

範圍

#

這是一個 已設定版本 變更,僅適用於語言版本 3.0 或更新版本。

dart:async

#
  • 下列宣告只能實作,不能擴充

    • StreamConsumer
    • StreamIterator
    • StreamTransformer
    • MultiStreamController

    這些宣告都沒有包含任何要繼承的實作。它們標示為 interface 表示它們只打算作為介面。

dart:core

#
  • Function 類型不再能實作、擴充或混合。自 Dart 2.0 起,寫 implements Function 是為了向後相容,但沒有任何效果。在 Dart 3.0 中,Function 類型是最後的,不能做子類型,避免程式碼錯誤地假設它有效。

  • 下列宣告只能實作,不能擴充

    • Comparable
    • Exception
    • Iterator
    • Pattern
    • Match
    • RegExp
    • RegExpMatch
    • StackTrace
    • StringSink

    這些宣告都沒有包含任何要繼承的實作。它們標示為 interface 表示它們只打算作為介面。

  • 下列宣告不再能實作或擴充

    • MapEntry
    • OutOfMemoryError
    • StackOverflowError
    • Expando
    • WeakReference
    • Finalizer

    MapEntry 值類別受到限制,以啟用後續最佳化。其餘類別與平台緊密結合,不打算作為子類別或實作。

dart:collection

#
  • 下列介面不再能擴充,只能實作

    • Queue
  • 下列實作類別不再能實作

    • LinkedList
    • LinkedListEntry
  • 下列實作類別不再能實作或擴充

    • HasNextIterator(也已棄用。)
    • HashMap
    • LinkedHashMap
    • HashSet
    • LinkedHashSet
    • DoubleLinkedQueue
    • ListQueue
    • SplayTreeMap
    • SplayTreeSet

Dart 3 工具變更

#

已移除工具

#

過去 Dart 團隊提供許多較小的開發人員工具,例如用於格式化程式碼 (dartfmt)、分析程式碼 (dartanalyzer) 等。在 Dart 2.10 (2020 年 10 月) 中,我們推出了新的統一 Dart 開發人員工具,dart 工具

範圍

#

這是一個 未設定版本 變更,適用於所有 Dart 3 程式碼。

症狀

#

在 Dart 3 中,這些較小的工具不存在,並已由新的合併 dart 工具取代。

遷移

#

使用 dart 工具中提供的新子指令

歷史工具dart 替換棄用終止
stagehanddart create2.142.14*
dartfmtdart format2.142.15
dart2nativedart compile exe2.142.15
dart2jsdart compile js2.172.18
dartdevcwebdev2.172.18
dartanalyzerdart analyze2.162.18
dartdocdart doc2.162.17
pubdart pub2.152.17

Null 安全移轉工具

#

下列的 null 安全性移轉指令已移除,因為 Dart 3 不支援沒有 null 安全性的程式碼

  • dart migrate
  • dart pub upgrade --null-safety
  • dart pub outdated --mode=null-safety

範圍

#

這是一個 未設定版本 變更,適用於所有 Dart 3 程式碼。

症狀

#

這些指令會失敗。

遷移

#

使用 Dart 2.19 移轉至 null 安全性

分析器設定檔

#

用於啟用更嚴格檢查的 分析器設定選項 已變更。

範圍

#

這是一個 未設定版本 變更,適用於所有 Dart 3 程式碼。

症狀

#

以前的設定選項會失敗,並顯示類似下列的警告

The option 'implicit-casts' is no longer supported.
Try using the new 'strict-casts' option.

遷移

#

取代分析器設定的這部分

yaml
analyzer:
  strong-mode:
    implicit-casts: false
    implicit-dynamic: false

yaml
analyzer:
  language:
    strict-casts: true
    strict-raw-types: true

其他工具變更

#
  • 已預設隱藏已棄用的 Observatory。我們建議使用 DevTools
  • 指令 dart format fix 已被 dart fix #1153 取代。
  • 已清除 SDK 中為 Dart 網頁編譯器捆綁的快照檔案 #50700
  • dart format 的輸出已針對 一些程式碼 稍作變更。
  • 結束 Windows 上 pub-cache 舊位置的向下相容性。在 Dart 3 之前,%APPDATA%\Pub\Cache 是 pub-cache 的備用位置。從 Dart 3 開始,預設的 pub-cache 位於 %LOCALAPPDATA%\Pub\Cache。如果您已將全域啟用的套件新增至您的 PATH,請考慮更新 PATH 以包含 %LOCALAPPDATA%\Pub\Cache\bin

範圍

#

這是一個 未設定版本 變更,適用於所有 Dart 3 程式碼。