Dart 系列---密封类(sealed )

密封类(sealed )是 Dart 3 中引入的新功能。

使用事项

您还需要在 pubspec.yaml 文件中将 Dart 3 设置为 sdk:sdk: ">=3.0.0 <4.0.0"

scala 复制代码
sealed class Animal {} 
class Dog extends Animal {}
class Pig extends Animal {}
class Cat extends Animal {}

将类标记为sealed有 2 个主要效果:

  1. 该类为 abstract(您无法创建 Animal 的具体实例)
  2. 所有子类型必须在同一个文件中定义

怎么在Dart3 之前实现类似效果

在 dart 2 中,您使用 abstract 而不是 sealed

scala 复制代码
/// Before dart 3.0 (no `sealed` classes)
abstract class Animal {} 
class Dog extends Animal {}
class Pig extends Animal {}
class Cat extends Animal {}

abstract 类不允许您创建其类型的具体实例,(Animal()就是不可能的)。这方面对于 sealed 来说是相同的,所以 任何sealed 类也是 abstract类。编译器里面会发出一下预警:

css 复制代码
Abstract classes can't be instantiatedTry creating an instance of a concretesubtype. dart(instantiate abstract_class)

主要区别在于, abstract 类对于sealed 来说不可能在编译时知道主类的所有子类型。 相反,需要在同一个库中定义所有子类型 ()。

scala 复制代码
import 'animal.dart'; 
/// This works in Dart 2, since the class is not `sealed`
/// but it does not work in Dart 3 🔒
class Dog extends Animal {}

这在 Dart 2 中是完全可能的。在 Dart 3 中,使用 sealed 代替,您将得到以下编译时错误 invalid_use_of_type_outside_library

kotlin 复制代码
The class 'Animal' can't be extended, implemented, or mixed in outside
of its library because it's a sealed
class. dart(invalid_use_of_type_outside_library)

为啥要使用sealed

对于 sealed 类,编译器知道该类的所有可能的子类型,因为这些都是在同一个库中定义。 实际上,这会解锁详尽的模式匹配:当您忘记匹配子类型时,您将收到编译时错误

例如在使用 switch ,你会在 dart 3 中收到 编译时错误, 当你忘记时通知你处理子类型(因为编译器知道所有可能的情况):

arduino 复制代码
/// Did you forget `Cat` in your `switch`?
////// In Dart 2 no error when you forget a subtype 
////// In Dart 3 you get a compile-time error instead 
switch (animal) {
case Dog(): 
  print("Dog"); 
  break; 
case Pig(): 
  print("Pig"); 
  break; 
}

上面的代码在 dart 3 中会出现以下错误 (non_exhaustive_switch_statement):

csharp 复制代码
The type 'Animal' is not exhaustively matched by the switch cases sinceit doesn't match 'Cat()!

Try adding a default case or cases that match Cat()'.dart(non exhaustive switch statement)

密封型的规范

标记sealed的类型有两个限制:

  • 如果它是一个类,则类型本身不能直接构造。class是 隐式 abstract
  • 该类型的所有直接子类型必须在同一个库中定义。任何 直接实现、扩展或混合在密封类型中的类型必须是 在定义密封类型的库中定义。

作为对这些限制的回报,密封提供了两个有用的特性 详尽性检查:

  • 密封类型的所有直接子类型都可以轻松找到并 列举了。
  • 密封类型的任何具体实例也必须是 at 的实例 至少一种已知的直接亚型。换句话说,如果你匹配 密封类型的值,并且您有所有直接子类型的情况, 编译器知道这些情况是详尽的。

有关更多详细密封类型功能规范信息,您可以阅读密封类型功能规范一文

相关推荐
明月_清风2 分钟前
爆破前端生态!Cloudflare 收购 Vite 背后,前端开发者会迎来什么变化?
前端·vite
光影少年2 分钟前
react的useMemo 如何优化?
前端·react.js·掘金·金石计划
星栈2 分钟前
Makepad、egui、Dioxus、Tauri:Rust GUI 到底怎么选
前端·rust
ai_coder_ai3 分钟前
如何在自动化脚本中实现定时操作?
java·前端·javascript
努力早日退休4 分钟前
一个 9999px 引发的跨平台血案:小程序离屏隐藏元素的滚动兼容性问题
前端·javascript
嘟嘟071719 分钟前
前端异步编程完全指南:从json-server到DeepSeek大模型接口调用
前端
用户0595401744619 分钟前
大模型多轮对话“失忆”踩坑实录:一次线上事故让我排查了48小时,最终靠 Playwright + Pytest 把记忆锁死
前端·css
橘子星19 分钟前
前端薅数据神器 Fetch:不用翻墙,在线拿捏后端与 AI 接口
前端·后端
步步为营DotNet21 分钟前
探索.NET 11:Blazor 在跨平台客户端应用开发的进阶实践
前端·asp.net·.net
Hello馒头儿23 分钟前
vue3+uniapp经典hook方式实现一个更多加载的列表组件
前端·javascript·vue.js