如果你学过 Kotlin,再来看 Dart 的
sealed class,你会发现:
它们解决的是同一个问题,只是语法不同。
这篇文章,我不讲 API,不讲语法细节,只讲一件事:
👉 为什么 sealed 是"数据建模"的正确方式?
一、从一个最常见的场景说起:接口返回值
Dart
class ApiResult {
final int code;
final String? msg;
final Object? data;
const ApiResult({
required this.code,
this.msg,
this.data,
});
}
tips:
无论是 Android、Flutter 还是后端,你一定见过这种接口返回:
// 成功
{ "code": 0, "data": { "name": "Tom" } }
// 失败
{ "code": 1001, "msg": "参数错误" }
很多人会在代码里写成这样:
Dart
class ApiResult {
int code;
String? msg;
dynamic data;
}
然后使用时:
Dart
if (result.code == 0) {
use(result.data);
} else {
showError(result.msg);
}
❌ 这种写法的问题
-
data/msg大量 nullable -
结构不清晰
-
容易写错
-
IDE 无法提示遗漏分支
-
逻辑靠"约定"而不是"类型"
这时候你其实已经在用 enum 的方式思考问题了,只是写得很原始。
二、Kotlin 的解法:sealed class(关键转折点)
Kotlin 很早就意识到这个问题,于是给了我们 sealed class。
Kotlin 的标准写法
Kotlin
sealed class Result
data class Success(val data: User) : Result()
data class Error(val message: String) : Result()
object Loading : Result()
使用时:
Dart
when (result) {
is Success -> show(result.data)
is Error -> showError(result.message)
Loading -> showLoading()
}
Kotlin 在这里解决了什么?
✔ 状态是有限的
✔ 每种状态有不同的数据结构
✔ 编译器强制你处理所有情况
✔ 不可能写出"成功却没有数据"的代码
👉 这不是语法糖,这是建模能力的提升
三、Dart 的 sealed:本质和 Kotlin 一模一样
Dart 3 引入 sealed class 后,表达能力终于和 Kotlin 对齐。
Dart 写法
Dart
sealed class Result {}
class Success extends Result {
final User data;
Success(this.data);
}
class Error extends Result {
final String message;
Error(this.message);
}
class Loading extends Result {}
使用时:
Dart
switch (result) {
case Success(:final data):
show(data);
case Error(:final message):
showError(message);
case Loading():
showLoading();
}
👉 这和 Kotlin 的 when 是完全等价的设计思想。
四、为什么说 sealed 比 enum 高一个维度?
enum 只能表示「状态」
Kotlin
enum Status { loading, success, error }
它只能告诉你:现在是哪种状态。
但它不能告诉你:
-
success 的数据是什么
-
error 的错误信息是什么
你只能额外写:
Dart
class State {
Status status;
Object? data;
String? error;
}
这就是很多项目里「一堆 nullable 字段」的来源。
sealed 表示的是「状态 + 数据结构」
Dart
sealed class State {}
class Success extends State {
final Data data;
}
class Error extends State {
final String message;
}
这才是类型系统该干的事。
五、统一思想:sealed 本质是什么?
你现在可以这样理解:
sealed 是"带数据的 enum"
是"结构化状态"
是"业务状态的建模工具"
换句话说:
| 维度 | enum | sealed |
|---|---|---|
| 表达能力 | 只能表示值 | 可以表达结构 |
| 是否携带数据 | ❌ | ✅ |
| 类型安全 | 一般 | 强 |
| 适合场景 | 简单状态 | 业务状态 / 网络返回 |
| Kotlin / Dart 推荐 | ❌ | ✅ |
六、为什么 sealed 特别适合网络层 / 异步 / UI 状态?
因为这些场景天然符合:
同一时刻,只能处于一种状态
例如:
- 网络请求:Loading / Success / Error
- 页面状态:Empty / Loading / Content / Error
- 任务执行:Running / Done / Failed
而 sealed 正是为这种「互斥状态 + 不同数据结构」设计的。
七、你现在的理解,其实已经是"架构级"
你现在已经意识到:
-
sealed ≠ 语法糖
-
sealed 是一种 建模方式
-
sealed = 现代语言的核心能力
-
Kotlin / Dart / Rust / Swift 本质一致
这说明你已经从:
❌「怎么写代码」
➡️
✅「怎么设计数据结构」
八、最终总结(结论)
enum 是值的枚举,
sealed 是"类型 + 数据"的枚举。
sealed 不是为了少写代码,
而是为了让"错误写不出来"。