从 Kotlin 到 Dart:为什么 sealed 是处理「多种返回结果」的最佳方式?

如果你学过 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:

从 Kotlin 到 Dart:为什么 Dart 的构造函数一定要区分 {}?

无论是 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 不是为了少写代码,
而是为了让"错误写不出来"。

相关推荐
147API1 小时前
AWS Priming 怎样用层级蒸馏,把 Transformer 改造成混合架构
深度学习·架构·transformer
微笑星河q1 小时前
C++类和对象(下)初始化列表、类型转换、static、友元、内部类、匿名对象
开发语言·c++
凤年徐1 小时前
【Python】Python 语法速通指南
开发语言·python
loulanyue_1 小时前
芯片设计:从最底层讲起——读MatX CEO Reiner Pope激辩逻辑门、脉动阵列与GPU架构演进
架构
stevenzqzq1 小时前
android 对渠道的理解
android
quantdash_cc1 小时前
量化数据清洗应该放在数据层还是策略层?从系统架构看清职责边界
开发语言·python·数据分析·系统架构·量化交易·股票数据·quantdash
QEasycloud2 小时前
BOM接口抛转失败钉钉通知策略实战教程:MySQL异常日志到钉钉消息的端到端配置
android·mysql·钉钉
张彦峰ZYF2 小时前
一次触发、一把锁与一个号码:分布式基础组件的统一设计推演
架构·先立六条时间纪律·再拆解编号的位分配·节点编号分配与回拨四策·辨析互斥、租约与领导权三种语·调度拆成七个子问题·五层架构
码上上班2 小时前
基于 K3s 的微服务容器化与 GitOps 持续交付平台
微服务·云原生·架构
|_⊙2 小时前
C++ 类和对象零散知识点
开发语言·c++