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

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

相关推荐
liulian091620 分钟前
Flutter for OpenHarmony 跨平台开发:BMI计算器功能实战指南
flutter·华为
donecoding33 分钟前
一个 sudo 引发的血案:npm 全局包权限错乱彻底修复
前端·node.js·前端工程化
风骏时光牛马37 分钟前
Raku正则匹配与数据批量处理实操案例
前端
nbwenren40 分钟前
2026实测:Gemini 3 镜像站视觉能力实践——拍照原型图,一键生成 HTML+CSS 代码
前端·css·html
Lee川43 分钟前
Prisma 实战指南:像搭积木一样设计古诗词数据库
前端·数据库·后端
jinanwuhuaguo1 小时前
(第二十九篇)OpenClaw 实时与具身的跃迁——从异步孤岛到数字世界的“原住民”
前端·网络·人工智能·重构·openclaw
广州华水科技1 小时前
深度测评2026年单北斗GNSS位移监测系统推荐,与高口碑变形监测设备一同引领行业新风尚
前端
Alice-YUE2 小时前
【js高频八股】防抖与节流
开发语言·前端·javascript·笔记·学习·ecmascript
是上好佳佳佳呀3 小时前
【前端(十一)】JavaScript 语法基础笔记(多语言对比)
前端·javascript·笔记