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 的实例 至少一种已知的直接亚型。换句话说,如果你匹配 密封类型的值,并且您有所有直接子类型的情况, 编译器知道这些情况是详尽的。

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

相关推荐
汉堡大王952713 分钟前
一张图三句需求,我用 Trae Work 做了一块能看日出日落和月相的天文机械表
前端·后端·github
小小善后师23 分钟前
用 Canvas + AI 实现登录页的 Logo 粒子动画
前端·vue.js
Amos_Web23 分钟前
Rspack 源码解析(十六):多类型资源如何进入 Compilation.assets
前端·rust·前端框架
GAMC26 分钟前
chrome-devtools-mcp:让 AI 编码助手真正"看见"浏览器
前端·人工智能
deli00726 分钟前
高尔顿板:把球一颗颗丢下去,为什么最后总堆成一座钟形山
前端
java_nnnn29 分钟前
JavaEE进阶-CSS初识
java·前端·css·java-ee·html
good_ideal31 分钟前
从零实现一个自动提交 PR 的 MCP 工具:用 Skill 串起 Git 与 Azure DevOps
前端
喜欢吃豆33 分钟前
Agent 前端协议正在分层:彻底讲清 MCP Apps、AG-UI 与 A2UI
前端·大模型
赵锦川34 分钟前
css代替表格
前端·css
其实防守也摸鱼1 小时前
内网安全防护实践:从攻击视角理解防御要点
java·前端·安全·架构·自动化·nps