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

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

相关推荐
xjt_090113 分钟前
基于 Vue 3 构建企业级 Web Components 组件库
前端·javascript·vue.js
renke336422 分钟前
Flutter for OpenHarmony:构建一个 Flutter 色彩调和师游戏,RGB 空间探索、感知色差计算与视觉认知训练的工程实现
flutter·游戏
我是伪码农25 分钟前
Vue 2.3
前端·javascript·vue.js
王码码203530 分钟前
Flutter for OpenHarmony 实战之基础组件:第三十一篇 Chip 系列组件 — 灵活的标签化交互
android·flutter·交互·harmonyos
夜郎king1 小时前
HTML5 SVG 实现日出日落动画与实时天气可视化
前端·html5·svg 日出日落
夏幻灵2 小时前
HTML5里最常用的十大标签
前端·html·html5
ujainu2 小时前
Flutter + OpenHarmony 实现经典打砖块游戏开发实战—— 物理反弹、碰撞检测与关卡系统
flutter·游戏·openharmony·arkanoid·breakout
Mr Xu_2 小时前
Vue 3 中 watch 的使用详解:监听响应式数据变化的利器
前端·javascript·vue.js
未来龙皇小蓝2 小时前
RBAC前端架构-01:项目初始化
前端·架构
微祎_2 小时前
构建一个 Flutter 点击速度测试器:深入解析实时交互、性能度量与响应式 UI 设计
flutter·ui·交互