ZetCode

Dart 密封类

最后修改日期:2025 年 6 月 5 日

本教程探讨 Dart 密封类,演示它们在创建用于状态管理和模式匹配的类型安全、详尽的层级结构中的用法。

Dart 中的密封类是一个使用 sealed 关键字标记的特殊抽象类。它限制其子类只能在同一个库中定义,从而使编译器能够了解所有可能的子类。这允许在 switch 表达式中使用详尽的模式匹配,确保所有情况都得到处理,从而提高类型安全性并减少运行时错误。

Dart 密封类概述

密封类非常适合模拟有限状态层级,例如 UI 状态、网络响应或代数数据类型。它们利用 Dart 的模式匹配来简洁地处理每个子类,通常使用解构属性以直接访问的 switch 表达式。

功能 描述 示例
密封 限制子类在同一个库中 sealed class Shape {}
子类 固定的实现集 class Circle extends Shape {}
模式匹配 详尽的 switch 处理 switch (shape) { case Circle(): ... }

用于形状的基本密封类

此示例定义了一个用于几何形状的密封类层级,并使用模式匹配来计算它们的面积。

shapes.dart
sealed class Shape {}

class Circle extends Shape {
  final double radius;
  Circle(this.radius);
}

class Square extends Shape {
  final double side;
  Square(this.side);
}

class Triangle extends Shape {
  final double base;
  final double height;
  Triangle(this.base, this.height);
}

double calculateArea(Shape shape) {
  switch (shape) {
    case Circle(:final radius):
      return 3.14 * radius * radius;
    case Square(:final side):
      return side * side;
    case Triangle(:final base, :final height):
      return 0.5 * base * height;
  }
}

void main() {
  var circle = Circle(5);
  var square = Square(4);
  var triangle = Triangle(3, 6);

  print('Circle area: ${calculateArea(circle)}');
  print('Square area: ${calculateArea(square)}');
  print('Triangle area: ${calculateArea(triangle)}');
}

Shape 密封类有三个子类:CircleSquareTrianglecalculateArea 函数使用 switch 表达式来计算面积,解构 radius 等属性以进行简洁访问。编译器确保覆盖所有情况,防止未处理的状态。

$ dart run shapes.dart
Circle area: 78.5
Square area: 16.0
Triangle area: 9.0

网络请求状态

密封类可用于模拟网络请求状态,例如加载、成功或错误条件,并提供类型安全的处理。

http_state.dart
sealed class HttpState {}

class Loading extends HttpState {}

class Error extends HttpState {
  final String message;
  Error(this.message);
}

class Loaded extends HttpState {
  final String data;
  Loaded(this.data);
}

void handleState(HttpState state) {
  switch (state) {
    case Loading():
      print('⏳ Loading...');
    case Loaded(:final data):
      print('✅ Success! Response: $data');
    case Error(:final message):
      print('❌ Error: $message');
  }
}

void main() {
  handleState(Loading());
  handleState(Loaded('Data loaded successfully!'));
  handleState(Error('Failed to load data.'));
}

HttpState 密封类表示网络状态。Loading 表示正在进行的请求,Loaded 包含响应数据,Error 存储错误消息。handleState 函数使用模式匹配来处理每种状态,确保所有可能性都得到详尽处理。

$ dart run http_state.dart
⏳ Loading...
✅ Success! Response: Data loaded successfully!
❌ Error: Failed to load data.

带工厂构造函数的密封类

密封类可以使用工厂构造函数来创建子类的实例,为结果处理提供干净的 API。

result.dart
sealed class Result<T> {
  const Result();
  factory Result.success(T value) = Success<T>;
  factory Result.failure(String error) = Failure<T>;
}

class Success<T> implements Result<T> {
  final T value;
  Success(this.value);
}

class Failure<T> implements Result<T> {
  final String error;
  Failure(this.error);
}

void processResult(Result<int> result) {
  switch (result) {
    case Success(:final value):
      print('Success with value: $value');
    case Failure(:final error):
      print('Failure with error: $error');
  }
}

void main() {
  Result<int> successResult = Result.success(42);
  Result<int> failureResult = Result.failure('An error occurred');

  processResult(successResult);
  processResult(failureResult);
}

Result<T> 密封类使用泛型来模拟成功或失败的结果。工厂构造函数 Result.successResult.failure 创建 SuccessFailure 实例。processResult 函数使用模式匹配来处理结果,直接访问 valueerror

$ dart run result.dart
Success with value: 42
Failure with error: An error occurred

用户认证状态

密封类可以模拟用户认证状态,例如未认证、已认证或访客访问,并提供类型安全的处理。

auth_state.dart
sealed class AuthState {}

class Unauthenticated extends AuthState {}

class Authenticated extends AuthState {
  final String userId;
  Authenticated(this.userId);
}

class Guest extends AuthState {
  final String sessionId;
  Guest(this.sessionId);
}

void handleAuth(AuthState state) {
  switch (state) {
    case Unauthenticated():
      print('🔓 Please log in to continue.');
    case Authenticated(:final userId):
      print('👤 Logged in as user: $userId');
    case Guest(:final sessionId):
      print('🌐 Guest access with session: $sessionId');
  }
}

void main() {
  handleAuth(Unauthenticated());
  handleAuth(Authenticated('user123'));
  handleAuth(Guest('session456'));
}

AuthState 密封类定义了认证状态。Unauthenticated 表示未登录,Authenticated 包含用户 ID,Guest 包含会话 ID。handleAuth 函数使用模式匹配来处理每种状态,确保所有情况都得到覆盖。

$ dart run auth_state.dart
🔓 Please log in to continue.
👤 Logged in as user: user123
🌐 Guest access with session: session456

数学表达式

密封类可以表示数学表达式,通过模式匹配实现递归求值,用于复杂计算。

expression.dart
sealed class Expression {}

class Number extends Expression {
  final double value;
  Number(this.value);
}

class Add extends Expression {
  final Expression left;
  final Expression right;
  Add(this.left, this.right);
}

class Multiply extends Expression {
  final Expression left;
  final Expression right;
  Multiply(this.left, this.right);
}

double evaluate(Expression expr) {
  switch (expr) {
    case Number(:final value):
      return value;
    case Add(:final left, :final right):
      return evaluate(left) + evaluate(right);
    case Multiply(:final left, :final right):
      return evaluate(left) * evaluate(right);
  }
}

void main() {
  var expr = Add(
    Number(2),
    Multiply(Number(3), Number(4)),
  );
  print('Result: ${evaluate(expr)}');
}

Expression 密封类使用 NumberAddMultiply 子类来模拟数学表达式树。evaluate 函数使用模式匹配递归计算结果,处理表达式 2 + (3 * 4) 得到 14。

$ dart run expression.dart
Result: 14.0

来源

Dart 密封类 - 语言参考

本教程演示了 Dart 密封类,展示了它们在创建用于状态管理和模式匹配的类型安全、详尽的层级结构方面的强大功能。

作者

我叫 Jan Bodnar,是一位热情的程序员,拥有丰富的经验。自 2007 年以来,我撰写了超过 1,400 篇文章和 8 本电子书,并拥有十多年的编程教学经验。

列出 所有 Dart 教程