Dart 3 遷移指南
Dart 3 是一個主要版本,為 Dart 引入了新的核心功能:記錄、模式和類別修飾詞。
除了這些新功能之外,Dart 3 還包含許多可能會破壞現有程式碼的變更。
本指南將協助您解決升級到 Dart 3後可能遇到的任何遷移問題。
簡介
#未版本化與版本化變更
#以下列出的潛在破壞性變更分為兩類
未版本化變更:這些變更會在升級到 Dart 3.0 SDK 或更高版本後影響任何 Dart 程式碼。沒有任何方法可以「關閉」這些變更。
版本化變更:這些變更僅在套件或應用程式的語言版本設定為 >= Dart 3.0 時適用。語言版本衍生自
pubspec.yaml
檔案中的sdk
下限約束。像這樣的 SDK 約束不會套用 Dart 3 版本化變更yamlenvironment: sdk: '>=2.14.0 <3.0.0'
但像這樣的 SDK 約束會套用
yamlenvironment: 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
environment:
sdk: '>=2.14.0 <3.0.0' # This is interpreted as '>=2.14.0 <4.0.0'
這允許開發人員將 Dart 3 健全的空值安全性與已經支援 2.12 空值安全性的套件一起使用,而無需進行第二次遷移,除非程式碼受到任何其他 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% 健全的空值安全
#Dart 2.12 在兩年多前引入了空值安全性。在 Dart 2.12 中,使用者需要使用 pubspec 設定啟用空值安全性。在 Dart 3 中,空值安全性是內建的;您無法關閉它。
範圍
#這是一個未版本化變更,適用於所有 Dart 3 程式碼。
徵兆
#在沒有空值安全性支援的情況下開發的套件,在解析具有 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
的任何語言版本來選擇退出空值安全性的函式庫,將導致分析或編譯錯誤
$ 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% 遷移以啟用空值安全性。這需要 Dart 2.19
SDK,而不是 Dart 3 SDK。若要了解如何先將您的應用程式或套件遷移以支援空值安全性,請查看空值安全遷移指南。
預設值的冒號語法
#基於歷史原因,具名選用參數可以使用 :
或 =
指定其預設值。在 Dart 3 中,僅允許使用 =
語法。
範圍
#這是一個版本化變更,僅適用於語言版本 3.0 或更高版本。
徵兆
#Dart 分析產生類似以下的錯誤
line 2 • Using a colon as a separator before a default value is no longer supported.
遷移
#從使用冒號變更
int someInt({int x: 0}) => x;
變更為使用等號
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
的類別時,分析器會產生此診斷訊息。
遷移
#判斷類別是否旨在用作 mixin。
如果類別定義了介面,請考慮使用 implements
。
switch
#Dart 3.0 將 switch case 解釋為模式而不是常數運算式。
範圍
#這是一個版本化變更,僅適用於語言版本 3.0 或更高版本。
徵兆
#在 switch case 中找到的大多數常數運算式都是有效的模式,具有相同的含義 (具名常數、常值等)。這些行為將相同,並且不會出現任何徵兆。
少數不是有效模式的常數運算式將觸發invalid_case_patterns
lint。
遷移
#您可以透過在 case 模式前面加上 const
來還原為原始行為,使其不再被解釋為模式
case const [1, 2]:
case const {'k': 'v'}:
case const {1, 2}:
case const Point(1, 2):
您可以透過使用 dart fix
或從您的 IDE 執行此破壞性變更的快速修復。
continue
#如果 continue 語句的目標標籤不是迴圈 (for
、do
和 while
語句) 或 switch 成員,Dart 3 會報告編譯時期錯誤。
範圍
#這是一個版本化變更,僅適用於語言版本 3.0 或更高版本。
徵兆
#您將看到類似以下的錯誤
The label used in a 'continue' statement must be defined on either a loop or a switch member.
遷移
#如果變更行為是可以接受的,請變更 continue
以目標有效的標籤語句,該語句必須附加到 for
、do
或 while
語句。
如果您想保留行為,請將 continue
語句變更為 break
語句。在 Dart 的先前版本中,未針對迴圈或 switch 成員的 continue
語句的行為類似於 break
。
Dart 3 核心函式庫變更
#已移除的 API
#破壞性變更 #49529:核心函式庫已清理以移除已棄用多年的 API。以下 API 在 Dart 核心函式庫中不再存在。
範圍
#這是一個未版本化變更,適用於所有 Dart 3 程式碼。
dart:core
#- 移除了已棄用的
List
建構子,因為它不是空值安全的。請使用清單常值 (例如,空清單使用[]
,或空類型清單使用<int>[]
) 或List.filled
。這僅影響非空值安全程式碼,因為空值安全程式碼已經無法使用此建構子。 - 移除了
int.parse
、double.parse
和num.parse
上已棄用的onError
引數。請改用tryParse
方法。 - 移除了已棄用的
proxy
和Provisional
註解。原始的proxy
註解在 Dart 2 中沒有任何作用,而Provisional
類型和provisional
常數僅在 Dart 2.0 開發過程中內部使用。 - 移除了已棄用的
Deprecated.expires
getter。請改用Deprecated.message
。 - 移除了已棄用的
CastError
錯誤。請改用TypeError
。 - 移除了已棄用的
FallThroughError
錯誤。先前拋出此錯誤的 fall-through 種類在 Dart 2.0 中已成為編譯時期錯誤。 - 移除了已棄用的
NullThrownError
錯誤。此錯誤永遠不會從空值安全程式碼中拋出。 - 移除了已棄用的
AbstractClassInstantiationError
錯誤。在 Dart 2.0 中,呼叫抽象類別的建構子已成為編譯時期錯誤。 - 移除了已棄用的
CyclicInitializationError
。在空值安全程式碼中,不再在執行時期偵測到循環相依性。此類程式碼將改以其他方式失敗,可能會出現 StackOverflowError。 - 移除了已棄用的
NoSuchMethodError
預設建構子。請改用NoSuchMethodError.withInvocation
具名建構子。 - 移除了已棄用的
BidirectionalIterator
類別。現有的雙向迭代器仍然可以運作,它們只是沒有共用的超類型將它們鎖定為用於向後移動的特定名稱。
dart:async
#- 移除了已棄用的
DeferredLibrary
類別。請改用deferred as
匯入語法。
dart:developer
#- 移除了已棄用的
MAX_USER_TAGS
常數。請改用maxUserTags
。 - 移除了已棄用的
Metrics
、Metric
、Counter
和Gauge
類別,因為它們自 Dart 2.0 以來已損壞。
dart:html
#- 如先前宣布,已移除
Document
和HtmlDocument
中已棄用的registerElement
和registerElement2
方法。請參閱 #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
類型是 final 且無法子類型化,從而防止程式碼錯誤地假設它可以運作。以下宣告只能實作,不能擴充
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 替代工具 | 棄用 | 停止使用 |
---|---|---|---|
stagehand | dart create | 2.14 | 2.14* |
dartfmt | dart format | 2.14 | 2.15 |
dart2native | dart compile exe | 2.14 | 2.15 |
dart2js | dart compile js | 2.17 | 2.18 |
dartdevc | webdev | 2.17 | 2.18 |
dartanalyzer | dart analyze | 2.16 | 2.18 |
dartdoc | dart doc | 2.16 | 2.17 |
pub | dart pub | 2.15 | 2.17 |
空值安全遷移工具
#以下空值安全遷移命令已被移除,因為 Dart 3 不支援沒有空值安全的程式碼
dart migrate
dart pub upgrade --null-safety
dart pub outdated --mode=null-safety
範圍
#這是一個未版本化變更,適用於所有 Dart 3 程式碼。
徵兆
#這些命令將失敗。
遷移
#使用 Dart 2.19 遷移到空值安全。
分析器設定
#用於啟用更嚴格檢查的分析器設定選項已變更。
範圍
#這是一個未版本化變更,適用於所有 Dart 3 程式碼。
徵兆
#先前的設定選項將失敗並顯示類似以下的警告
The option 'implicit-casts' is no longer supported.
Try using the new 'strict-casts' option.
遷移
#取代分析器設定的這一部分
analyzer:
strong-mode:
implicit-casts: false
implicit-dynamic: false
使用
analyzer:
language:
strict-casts: true
strict-raw-types: true
其他工具變更
#- 已棄用的 Observatory 預設為隱藏。我們建議使用 DevTools。
- 命令
dart format fix
已被dart fix
取代 #1153。 - SDK 中針對 Dart Web 編譯器捆綁的快照檔案已清理 #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 程式碼。
除非另有說明,否則本網站上的文件反映 Dart 3.7.1。頁面上次更新時間為 2024-12-10。 檢視原始碼 或 回報問題。