0%

【文章翻譯】Dart 2.17: Productivity and integration

【文章內容使用 Gemini 1.5 Pro 自動翻譯產生】

Dart 2.17:提升生產力和整合能力

今天在 Google I/O 上,我們宣布推出新的 Dart SDK,版本 2.17。此版本基於我們提升生產力和平台可攜性的核心主題而構建。它提供了新的語言特性:支援成員的列舉、改進了向父類別轉發參數的功能,以及更靈活的命名參數。我們改進了工具,推出了 package:lints 的一個新的主要版本——我們的工具支援根據我們的最佳實務檢查 Dart 程式碼——並廣泛更新了核心函式庫 API 文件,其中包含豐富的程式碼範例。為了改進平台整合,我們提供了在 Flutter 外掛中使用 dart:ffi(原生 C 互通性)的新範本、對 RISC-V 處理器的實驗性支援,以及對簽署 macOS 和 Windows 可執行檔的支援。

Dart 2.17 reease banner

新的語言特性以提高生產力

我們不斷改進 Dart 語言,以提高您的生產力——透過新增新特性和改進現有特性。Dart 2.17 新增了對列舉成員的主要新支援,改進了您在建構函式中使用命名參數的方式,並使將參數轉發給父類別的程式碼更加簡潔,減少了重複。

增強的列舉支援成員

列舉非常適合表示一組離散的狀態。例如,我們可以將水建模為列舉 Water { frozen, lukewarm, boiling }。但是,如果我們想要在列舉上新增一些方法——例如,將每個狀態轉換為溫度,並支援將列舉轉換為字串,該怎麼辦?我們或許可以使用擴充方法來新增 waterToTemp() 方法,但我們必須小心地使其與列舉保持同步。對於字串轉換,我們更希望覆寫 toString(),但這一直不受支援。

在 Dart 2.17 中,我們現在全面支援列舉成員。這意味著我們可以新增儲存狀態的欄位、設定該狀態的建構函式、具有功能的方法,甚至覆寫現有的成員。你們中的許多人一直在要求此功能;這是我們在語言追蹤器中 投票數第三高的議題

對於我們的 water 範例,我們可以新增一個儲存溫度的 int 欄位和一個接受 int 的預設建構函式:

1
2
3
4
5
enum Water {

final int tempInFahrenheit;
const Water(this.tempInFahrenheit);
}

為了確保在建立列舉時調用建構函式,我們需要為每個列舉值調用它:

1
2
3
4
5
6
enum Water {
frozen(32),
lukewarm(100),
boiling(212);

}

為了支援轉換為字串,我們只需覆寫從 Object 繼承的 toString()

1
2
@override
String toString() => "The $name water is $tempInFahrenheit F.";

這樣,您就有一個完整的列舉,可以輕鬆地實例化,並且可以在其上調用方法:

1
2
3
void main() {
print(Water.frozen); // 輸出 “The frozen water is 32 F.”
}

這兩種方法的完整範例如下圖所示;我們發現新的 Dart 2.17 版本更易於閱讀和維護。

父類別初始化器

當您有一個類別繼承階層時,一種常見的模式是將一些建構函式參數傳遞給父類別的建構函式。為此,子類別需要 1) 在其自身的建構函式中列出每個參數,以及 2) 使用這些參數調用父類別建構函式。這會導致程式碼樣板化:大量重複,使程式碼更難閱讀,維護起來也更麻煩。

一些 Dart 社群成員幫助實現了這一點。GitHub 使用者 @roy-sianez 大約半年前提交了一個關於此的 語言議題;建議使用類似於 GitHub 使用者 @apps-transround 先前建議 的內容:我們或許可以透過引入一個新的結構來表示參數是在父類別中指定的來解決這個問題。我們認為這是一個很棒的主意,所以這已經新增到 Dart 2.17 中。從下面的範例中可以看出,這與 Flutter widget 程式碼特別相關。事實上,當我們將新特性應用於 Flutter 架構時,我們發現程式碼總共減少了 近兩千行

任何地方的命名參數

最後,我們改進了當您調用方法時命名參數的工作方式。以前,這些參數必須出現在方法的參數列表的最後。如果您希望將位置參數放在最後以使程式碼更具可讀性,這會很煩人。例如,請參閱以下對 List<T>.generate 建構函式的調用——以前,growable 參數必須放在最後,這使得它很容易在包含產生器本身的大型位置參數下方被遺漏。現在您可以按照自己的喜好排序它們,讓您可以將小型命名參數放在最前面,將產生器放在最後。

欲了解更多關於這三個特性的實際應用範例,請參閱我們更新的 列舉父類別初始化器命名參數 的範例。

生產力工具

繼續生產力主題,我們在核心工具中進行了多項改進。

在 Dart 2.14 中,我們引入了 package:lints,它與 Dart 分析器一起工作,幫助您編寫 Dart 程式碼,以防止錯誤,並使用規範的風格,從而更有效地進行程式碼審查。從那時起,分析器中提供了許多新的 lint,我們仔細地對其進行了分類,並從中為所有 Dart 程式碼選擇了 十個新的 lint,並專門為 Flutter 程式碼選擇了 兩個新的 lint。這些 lint 包括確保您的導入包含在您的 pubspec 檔案中,防止在類型參數上誤用 null 檢查,以及確保子屬性具有一致的風格。您可以使用一個簡單的命令升級到新的 lint:

  • 對於 Dart 套件:
    dart pub upgrade --major-versions lints
  • 對於 Flutter 套件:
    flutter pub upgrade --major-versions flutter_lints

SecureSockets 通常用於啟用透過 TLS 和 SSL 保護的 TCP sockets。在 Dart 2.17 之前,在開發過程中除錯這些 sockets 非常棘手,因為沒有辦法檢查安全資料流量。我們現在新增了對指定 keyLog 檔案的支援。指定後,當與伺服器交換新的 TLS 金鑰時,NSS 金鑰日誌格式 的一行文字會附加到檔案中。這使得網路流量分析器工具(例如 Wireshark)能夠解密透過 socket 傳送的內容。有關詳細資訊,請參閱 SecureSocket.connect() 的 API 文件。

由 dart doc 工具產生的 API 文件是大多數 Dart 開發人員學習新 API 的關鍵資產。雖然我們的 核心函式庫 API 長期以來都有豐富的文字描述,但許多開發人員告訴我們,他們更喜歡透過閱讀使用 API 的範例程式碼來學習 API。在 Dart 2.17 中,我們徹底修改了所有主要的程式碼函式庫,在瀏覽量最高的 200 個頁面中新增了範例程式碼,因此它們現在都有全面的範例程式碼。例如,比較 Dart 2.16 中 dart:convert 的文件 與 Dart 2.17 中更新的 頁面;希望這能使文件更易於使用。

生產力的提高不僅僅來自於我們為平台新增新特性,還來自於我們清理堆疊並移除不再使用的特性。這有助於保持我們平台的精簡,這對於新開發人員尤其重要。為此,我們從 dart:io 函式庫中移除了 231 行棄用的程式碼——如果您仍在使用這些棄用的 API,您可以使用 dart fix 升級到它們的替代品。我們也繼續努力移除 棄用的 Dart 命令列工具,這次移除了 dartdoc 工具(改用 dart doc)和 pub 工具(改用 dart pub 或 flutter pub)。

擴大我們的平台整合和支援

第二個核心主題是平台整合和支援。Dart 是一種真正的跨平台語言。雖然我們已經支援 各種平台,但我們仍在不斷改進,以確保您可以與每個支援的平台深度整合,並支援新興平台。

Dart FFI——我們與 C/原生程式碼互通的核心機制——是一種將 Dart 程式碼與現有原生平台程式碼整合的常用方法。在 Flutter 上,這可能是構建使用主機平台原生 API(例如 Windows win32 API)的 外掛 的好方法。在 Dart 2.17 和 Flutter 3 中,我們在 flutter 工具中新增了範本,因此您現在可以輕鬆建立 FFI 外掛,這些外掛具有由 dart:ffi 調用到原生程式碼的 Dart API。有關詳細資訊,請參閱 flutter.dev 上更新的 開發套件和外掛 頁面。

為了能夠在具有特定於其 ABI(應用程式二進位介面)的類型的平台上使用 FFI,FFI 現在支援特定於 ABI 的類型。例如,您現在可以使用 Long(C 語言中的 long)來正確表示具有特定於 ABI 大小的長整數,根據 CPU 架構,它可能是 32 位或 64 位。有關支援類型的完整列表,請參閱 AbiSpecificInteger API 頁面中的「實作者」列表。

當使用 Dart FFI 與原生平台深度整合時,您有時需要調整由 Dart 和原生程式碼分配的記憶體或其他資源(埠、檔案等)的清理。從歷史上看,這一直非常棘手,因為 Dart 是一種垃圾回收語言,會自動處理清理工作。Dart 2.17 透過引入 Finalizer 的概念來解決這個問題,Finalizer 包括一個 Finalizable 標記介面,用於「標記」不應過早完成或丟棄的物件,以及一個 NativeFinalizer 類別,可以附加到 Dart 物件上,以便在物件即將被垃圾回收時提供一個回調執行。這些一起允許在原生程式碼和 Dart 程式碼中執行清理程式碼。有關詳細資訊,請參閱 NativeFinalizer 的 API 文件中的描述和範例,或 WeakReferencesFinalizer 的文件,以了解在常規 Dart 程式碼中的類似支援。

我們對將 Dart 編譯為原生程式碼的支援是使 Flutter 應用程式具有出色的啟動效能和快速渲染的核心推動因素。第二個用例是使用 dart compile 將 Dart 編譯為可執行檔的能力。這些可執行檔可以在任何機器上獨立執行,而無需安裝 Dart SDK。Dart 2.17 中的另一個新功能是支援 簽署可執行檔,這使得在 Windows 和 macOS 上進行部署成為可能,因為在這些平台上通常需要簽署。

我們也繼續透過保持在新興平台的最前沿來擴大我們支援的平台集。RISC-V 是一種新的創新處理器指令集。RISC-V International 是一個全球非營利組織,擁有 RISC-V 規範,使指令集免費且開源。這仍然是一個新興平台,但我們對其潛力感到興奮,因此我們的 2.17.0-266.1.beta Linux 版本(或我們 beta 頻道 的更高版本)包含對它的實驗性支援。我們很樂意聽到您的回饋,所以請 提交議題發布 關於您的體驗!

開始使用 Dart 2.17!

我們希望今天的 Dart 2.17 版本能讓您興奮,提高您的生產力,並為您的應用程式實現更多的平台整合。要開始使用,您可以直接下載 Dart 2.17 版本,或者將其作為今天 Flutter 3 SDK 版本的一部分嵌入。

我們也邀請您查看我們為 Google I/O 提供的 新內容


Dart 2.17:生產力和整合 最初發佈在 Dart 上的 Medium,人們在那裡透過突出顯示和回應這個故事來繼續討論。