天天看點

Dart 3 正式釋出,100% 健全的空安全

作者:開源中國OSC

出品|開源中國

Dart 3 現已釋出,這是迄今為止最大的 Dart 版本,包含了三個主要改進:完成了 100% 健全的空安全;添加了記錄、模式和類修飾符的新語言特性;以及對未來進行了預覽,即,通過 Wasm 編譯擴大了對網絡原生代碼的平台支援。

Dart 3 正式釋出,100% 健全的空安全

100% 健全的空安全

Dart 3 已經成為了一種 100% 健全的空安全語言。100% 的空安全性為 Dart 帶來了健全的類型系統。你可以相信,如果一個類型說一個值不是 null,那麼它永遠不可能是 null。這避免了某些類别的編碼錯誤,例如空指針異常。它還允許編譯器和運作時以沒有空安全性無法實作的方式優化代碼。雖然這種設計會使得遷移變得有點困難,但開發團隊認為,他們為 Dart 做出了正确的選擇。

Dart 3 正式釋出,100% 健全的空安全

預計絕大多數已遷移到 null safety 的包和應用程式都可以與 Dart 3 一起使用。在少數情況下,Dart 3 中的少量相關清理可能會影響某些代碼。一些舊的核心庫 API 已被删除(#34233、#49529)并且一些工具已被調整(#50707)。如果使用者在遷移到使用 Dart 3 SDK 時遇到任何問題,可查閱 Dart 3 遷移指南。

主要語言特性 —— 記錄、模式和類修飾符

Dart 3 不僅僅是基于現有基礎作出改變,它還涉及添加重要的新特性和功能。

使用記錄建構結構化資料

借助記錄,你可以使用簡潔明了的文法建構結構化資料。

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

記錄是值類型,沒有辨別。這使得編譯器能夠在某些情況下完全擦除記錄對象。記錄還帶有自動定義的 == 運算符和 hashCode 函數。更多詳細資訊可檢視文檔。

用模式和模式比對來處理結構化資料

記錄簡化了建構結構化資料的方式。這不會取代使用類來建構更正式的類型層次結構。它隻是提供了另一種選擇。在任何一種情況下,你都可能希望将該結構化資料分解為單獨的元素以使用它們。這就是模式比對發揮作用的地方。

考慮模式的基本形式。以下記錄模式将記錄解構為兩個新變量 name 和 height。然後可以像任何其他變量一樣使用這些變量,例如調用 print 時:

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

類似的模式也存在于 lists 和 maps 中。對于所有這些,你可以使用下劃線模式跳過單個元素:

var (String name, _) = userInfo(…);      

Dart 3 中還擴充了 switch 語句的功能和表現力。現在已經消除了在每個案例末尾添加 break 的需要,還支援邏輯運算符來組合案例。示例:

switch (charCode) {  case slash when nextCharCode == slash:
    skipComment();  case slash || star || plus || minus:
    operator(charCode);  case >= digit0 && <= digit9:
    number();  default:
    invalid();
}      

模式的一個強大功能是能夠檢查 “exhaustiveness”,此功能可確定 switch 可以處理所有可能的情況。

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 的處理:

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

if 語句也可以使用模式:

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!');
}      

更多詳情可檢視 patterns documentation 和 patterns codelab。

具有類修飾符的類的細粒度通路控制

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

類修飾符使 API 作者能夠僅支援一組特定的功能。預設值保持不變。開發團隊希望 Dart 保持簡單易用。是以,像以前一樣,可以構造、擴充和實作正常類,如以下示例所示:

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

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

  • 使用 interface class,你可以定義一個契約供其他人實施。不能擴充接口類。
  • 使用 base class,你可以確定類的所有子類型都繼承自它,而不是實作它的接口。這確定私有方法在所有執行個體上都可用。
  • 使用 final class,你可以關閉類型層次結構以防止你自己的庫之外的任何子類。作為一個 sample 好處,這允許 API 所有者添加新成員,而不會冒破壞 API 使用者更改的風險。

更多詳情可檢視文檔:https://dart.dev/language/class-modifiers

展望未來

  • 檢視 Dart 3 之後的次要版本是否需要對記錄、模式和類修飾符進行更新。
  • 研究一些更小、更增量的功能,這些功能完全不具破壞性,并且專注于提高開發者的生産力,而沒有遷移成本。正在探索的兩個示例是用于使用零成本 “wrappers” 以包裝現有類型的内聯類,和 primary constructors,它引入了一種更簡潔的文法來定義具有幾個字段和一個 primary constructor 的類。
  • 關注宏(也稱為元程式設計),以便更好地反序列化 JSON(和類似的),并啟用資料類。
  • 目前已經支援用 dart:fi 編譯成 C 庫的代碼的互操作。正在努力将其擴充到支援 Android 上的 Java 和 Kotlin 互操作,以及 iOS/MacOS 上的 Objective C 和 Swift 互操作。
  • 編譯為 WebAssembly —— 使用 native code 定位 web

更多詳情可檢視官方公告:https://medium.com/dartlang/announcing-dart-3-53f065a10635