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

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

相关推荐
奇迹_h4 小时前
打造你的HTML5打地鼠游戏:零基础入门实践
前端
SuperEugene4 小时前
Vue生态精选篇:Element Plus 的“企业后台常用组件”用法扫盲
前端·vue.js·面试
Neptune14 小时前
JavaScript回归基本功之---类型判断--typeof篇
前端·javascript·面试
贾铭4 小时前
如何实现一个网页版的剪映(三)使用fabric.js绘制时间轴
前端·后端
子兮曰5 小时前
后端字段又改了?我撸了一个 BFF 数据适配器,从此再也不怕接口“屎山”!
前端·javascript·架构
万少7 小时前
使用Trae轻松安装openclaw的教程-附带免费token
前端·openai·ai编程
浪浪山_大橙子7 小时前
OpenClaw 十分钟快速,安装与接入完全指南 - 推荐使用trae 官方 skills 安装
前端·人工智能
忆江南7 小时前
iOS 可视化埋点与无痕埋点详解
前端
离开地球表面_997 小时前
金三银四程序员跳槽指南:从简历到面试再到 Offer 的全流程准备
前端·后端·面试
_柳青杨7 小时前
跨域获取 iframe 选中文本?自己写个代理中间层,再也不求后端!
前端