0%

【文章翻譯】Announcing Dart 3

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

宣布 Dart 3

來自 Google I/O 2023 的問候。今天,我們將從山景城現場宣布 Dart 3——迄今為止最大的 Dart 版本!Dart 3 包含三個主要進展。首先,我們完成了通往 100% 聲稱空安全性的旅程。其次,我們為記錄、模式和類修飾符添加了主要的新語言功能。第三,我們正在預覽未來,在未來我們將透過 Wasm 編譯為 Web 提供原生程式碼,從而擴展我們的平台支援。讓我們深入了解細節。

100% 聲稱空安全性

在過去的四年中,我們將 Dart 演變為一種快速、可移植且現代的語言。現在,有了 Dart 3,它成為了 100% 聲稱空安全的語言!正如我們之前所 討論過的那樣,我們認為沒有其他程式設計語言曾經為現有的語言添加過聲稱空安全性。所以,這是一段漫長的旅程。

有了 Dart 中的 100% 空安全性,我們擁有一個 聲稱 的類型系統。您可以相信,如果類型表示值不為 null,那麼它永遠不會為 null。這避免了某些類型的編碼錯誤,例如空指標異常。它還允許我們的編譯器和運行時以在沒有空安全性時無法實現的方式優化程式碼。這個設計選擇涉及一個權衡。儘管遷移變得有點困難,但我們相信我們為 Dart 做出了正確的選擇。

遷移到 Dart 3

在實現聲稱空安全性方面,Dart 社群的不懈支援至關重要:pub.dev 上排名前 1000 的套件中有 99% 支援空安全性!

基於此,我們預計絕大多數已遷移到空安全性的套件和應用程式都可以在 Dart 3 中正常運行。在極少數情況下,Dart 3 中的少量相關清除可能會影響某些程式碼。一些遺留核心函式庫 API 已被移除(#34233#49529),並且一些工具已調整(#50707)。如果您在遷移到使用 Dart 3 SDK 時遇到任何問題,請參閱 Dart 3 遷移指南。除此之外,我們希望您能享受新的合理化核心函式庫和工具。

主要語言功能 - 記錄、模式和類修飾符

Dart 3 不僅僅是關於更改現有語言。它還包括添加重要的新功能和能力!這些包括記錄、模式和類修飾符。

使用記錄構建結構化資料

傳統上,Dart 函數只能返回單個值。因此,需要返回多個值的函數必須將這些值打包到其他資料類型中,例如映射或列表,或者定義可以保存這些值的新的類別。使用未類型化的資料結構會削弱類型安全性。必須定義新的類別僅用於攜帶資料,這在編碼過程中會增加摩擦。您已經很清楚地告訴我們:對多個返回值的語言請求是我們 排名第四 的問題。

使用記錄,您可以使用乾淨利落的語法構建結構化資料。考慮這個函數。它讀取 JSON blob 的名稱和年齡,並將它們都返回到一個記錄中:

1
2
3
(String, int) userInfo(Map<String, dynamic> json) {
return (json['name'] as String, json['height'] as int);
}

這對所有 Dart 開發人員來說應該很熟悉。記錄看起來像列表常量,例如 ['Michael', 'Product Manager' ],但使用括号而不是方括号。在 Dart 中,記錄是一個通用功能。它們可以用於函數返回值以外的其他用途。您也可以將它們存儲在變數中,將它們放入列表中,將它們用作映射中的鍵,或建立包含其他記錄的記錄。您可以添加未命名的欄位,就像我們在之前的示例中所做的那樣,以及命名的欄位,例如 (42, description: 'Meaning of life')

記錄是值類型,沒有身份。這使得我們的編譯器可以在某些情況下完全擦除記錄物件。記錄還帶有自動定義的 == 運算符和 hashCode 函數。記錄文件 具有更多詳細信息。

使用模式和模式匹配處理結構化資料

記錄簡化了您構建結構化資料的方式。這不會取代使用類別來構建更正式的類型層次結構。它只提供另一個選項。無論哪種情況,您可能都希望將這些結構化資料分解成其個別元素以進行處理。這就是模式匹配發揮作用的地方。

考慮一種基本的模式形式。以下記錄模式將記錄分解成兩個新的變數 nameheight。這些變數之後可以像任何其他變數一樣使用,例如在呼叫 print 時:

1
2
var (String name, int height) = userInfo({'name': 'Michael', 'height': 180});
print('User $name is $height cm tall.');

列表和映射也存在類似的模式。對於所有這些模式,您可以使用下劃線模式來跳過個別元素:

1
var (String name, _) = userInfo(...);

模式在 switch 語句中使用時效果顯著。Dart 從一開始就對 switch 提供了有限的支援。在 Dart 3 中,我們擴展了 switch 語句的功能和表現力。我們現在在這些情況下支援模式匹配。我們已經不需要在每個 case 的末尾添加 break。我們還支援邏輯運算符來組合 case。以下示例展示了一個乾淨利落的 switch 語句,它解析字元碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
switch (charCode) {
case slash when nextCharCode == slash:
skipComment();

case slash || star || plus || minus:
operator(charCode);

case >= digit0 && <= digit9:
number();

default:
invalid();
}

當您需要為每個 case 使用一個或多個語句時,switch 語句提供了很好的幫助。在某些情況下,您只想做的是計算一個值。對於這種情況,我們提供了一個非常簡潔的 switch 表達式。這類似於 switch 語句,但使用不同的語法,該語法針對表達式進行了微調。以下示例函數返回一個 switch 表達式的值,以計算當前日期的星期幾描述:

1
2
3
4
5
6
String describeDate(DateTime dt) => 
switch (dt.weekday) {
1 => 'Feeling the Monday blues?',
6 || 7 => 'Enjoy the weekend!',
_ => 'Hang in there.'
};

模式的一個強大功能是能夠檢查「窮舉性」。此功能確保 switch 處理所有可能的情況。在前面的示例中,我們正在處理 weekday 的所有可能值,weekday 是一個 int。我們透過組合針對特定值 1、6 或 7 的匹配語句,然後使用預設情況 _ 來處理剩餘情況,來窮舉所有可能的值。若要啟用對使用者定義的資料層次結構(例如類別層次結構)的這種檢查,請在類別層次結構頂部使用新的 sealed 修飾符,如以下示例所示:

1
2
3
4
5
6
7
sealed class Animal { ... }
class Cow extends Animal { ... }
class Sheep extends Animal { ... }
class Pig extends Animal { ... }

String whatDoesItSay(Animal a) =>
switch (a) { Cow c => '$c says moo', Sheep s => '$s says baa' };

這將返回以下錯誤,提醒我們漏掉了對最後一個可能的子類型 Pig 的處理:

1
2
line 6 • The type 'Animal' is not exhaustively matched by the switch cases
since it doesn't match 'Pig()'.

最後,if 語句也可以使用模式。在下面的示例中,我們正在使用 if-case 匹配一個映射模式來分解 JSON 映射。在其中,我們根據常量值(字串,例如 'name''Michael')和類型測試模式 int h 進行匹配,以讀取 JSON 值。如果模式匹配失敗,Dart 將執行 else 語句。

1
2
3
4
5
6
7
8
final json = {'name': 'Michael', 'height': 180};

// Find Michael's height.
if (json case {'name': 'Michael', 'height': int h}) {
print('Michael is $h cm tall.');
} else {
print('Error: json contains no height info for Michael!');
}

這僅觸及了您可以使用模式完成的所有事情。我們相信它們將在所有 Dart 程式碼中變得普遍。若要進一步了解,請查看 模式文件模式程式碼實驗室

使用類修飾符為類別提供細粒度的存取控制

第三個 Dart 3 語言功能是類修飾符。與我們期望每個 Dart 開發人員使用的記錄和模式不同,這更像是一個強大的使用者功能。它滿足了編寫大型 API 表面或構建企業級應用程式的 Dart 開發人員的需求。

類修飾符使 API 作者能夠僅支援特定功能集。不過,預設值保持不變。我們希望 Dart 保持簡單易懂。因此,和以前一樣,常規類別可以 構造擴展實作,如下面的示例所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Vehicle {
String make; String model;
void moveForward(int meters) { ... }
}

// Construct.
var myCar = Vehicle(make: 'Ford', model: 'T',);

// Extend.
class Car extends Vehicle {
int passengers;
}

// Implement.
class MockVehicle implements Vehicle {
@override void moveForward ...
}

類修飾符支援對此添加限制。考慮一些示例用例:

  • 使用介面類別,您可以為其他人定義一個要實作的合約。介面類別不能被擴展。
  • 使用基類別,您可以確保您類別的所有子類型都繼承自它,而不是實作其介面。這確保私有方法在所有實例上都可用。
  • 使用 final 類別,您可以關閉類型層次結構,防止在您自己的函式庫之外建立任何子類別。作為一個示例優點,這允許 API 擁有者添加新的成員,而不會冒著對 API 使用者造成重大變更的風險。

有關詳細信息,請參閱新的 類修飾符文件

未來展望

Dart 3 不僅僅是您今天可以使用的功能方面的一個重大進步。我們還將預覽一下下一步。

Dart 語言

記錄、模式和類修飾符是十分重要的新功能,因此,它們的設計部分可能存在可以改進的地方。我們將繼續監控 您的回饋,並查看是否需要在 Dart 3 後的次要版本中進行更新。

我們還正在考慮一些更小、更增量式的功能,這些功能完全不可破壞,並且專注於提高開發人員的生產力,而無需遷移成本。我們正在探索的兩個示例是 內聯類別,用於以零成本的「包裝器」包裝現有類型,以及 主建構函數;此功能引入了定義包含少數欄位和主建構函數的類別的更簡潔的語法。

我們之前討論過宏(也稱為 元程式設計)。我們特別關注這一點,以實現對 JSON(和類似資料)的更好的反序列化,以及啟用資料類別。考慮到元程式設計的規模和固有的風險,我們正在採取非常徹底的方法,因此我們沒有任何明確的時間表可以分享,即使是最終確定設計決定的時間表。

原生互操作

行動裝置和桌面的應用程式通常依賴於原生平台提供的許多 API,無論是通知、支付還是獲取手機的位置。傳統上,在 Flutter 中,這些 API 是透過構建外掛來存取的,這需要同時編寫 API 的 Dart 程式碼和大量平台特定程式碼以提供實作。

我們已經支援與編譯成 C 函式庫的程式碼進行互操作,可以使用 dart:ffi。我們目前正在努力擴展此支援,以支援 Android 上的 Java 和 Kotlin 互操作 以及 iOS/macOS 上的 Objective C 和 Swift 互操作。若要了解 Android 互操作的簡介,請查看新的 Google I/O 23 Android 互操作性影片

編譯成 WebAssembly - 使用原生程式碼定位 Web

WebAssembly(簡稱為 Wasm)作為一種平台中立的二進制指令格式,在 所有現代瀏覽器 中日益成熟。Flutter 架構已經使用 Wasm 一段時間了。這是我們將以 C++ 編寫的 SKIA 圖形渲染引擎透過 Wasm 編譯的模組傳遞到瀏覽器的方式。我們一直對使用 Wasm 部署 Dart 程式碼很感興趣,但我們一直受阻。Dart 與許多其他面向物件語言一樣,使用垃圾回收。在過去的一年中,我們已與 Wasm 生態系統中的多個團隊合作,為 WebAssembly 標準添加新的 WasmGC 功能。這現在在 Chromium 和 Firefox 瀏覽器中接近穩定狀態。

我們在將 Dart 編譯成 Wasm 模組方面的工作具有兩個針對 Web 應用程式的目標:

  • 載入時間:我們希望我們能夠使用瀏覽器載入速度更快的 Wasm 傳遞部署有效載荷,從而縮短到達使用者可以與 Web 應用程式互動的點所需的時間。
  • 效能:由 JavaScript 驅動的 Web 應用程式需要即時編譯才能實現良好的效能。Wasm 模組是更低階的,更接近機器碼,因此我們認為它們可以透過更少的卡頓和更一致的畫面速率提供更高的效能。
  • 語義一致性:Dart 對於我們支援的平台之間的高度一致性感到自豪。但是,在 Web 上,有一些例外。例如,Dart Web 目前在 數字的表示方式 方面有所不同。有了 Wasm 模組,我們將能夠將 Web 視為一個「原生」平台,其語義類似於其他原生目標。

我們很興奮地宣布今天首次預覽將 Dart 編譯成 Wasm!我們最初的重點是 Flutter Web 支援。這還處於早期階段,我們還有很多工作要做,但我們 邀請您進行嘗試,看看您是否像我們一樣興奮。

結語

感謝您耐心閱讀到結尾。我們希望這篇文章讓您對 Dart 3 感到興奮,Dart 3 目前已在獨立的 Dart SDKFlutter 3.10 SDK 中提供。

我們已使用聲稱空安全性、核心函式庫和工具清理對 Dart 語言進行了重大改進。有一些主要的新語言功能,使 Dart 透過記錄和模式變得更具表現力和簡潔性。對於大型 API 表面,類修飾符啟用了詳細的控制。我們還包括對 WebAssembly 的支援預覽。

有了所有這些功能,我們認為 Dart 3 展示了我們的長期願景:為在任何平台上構建快速應用程式構建最具生產力的程式設計語言。我們希望您也這麼認為!


宣布 Dart 3 最初發佈在 Dart 上的 Medium,人們在那裡透過突出顯示和回應這個故事來繼續討論。

http://creativecommons.org/licenses/by/4.0/