Menu
CoddyTech

密封类(Dart 3)

本课属于 Coddy Dart 学习旅程的“面向对象编程”单元。第 85 课,共 110 课。

Dart 3 引入了密封类,它们会限制哪些类可以继承或实现它们。当你将一个类标记为 sealed 时,只有同一文件中的类才能成为它的直接子类型。这样就创建了一个已知子类型的封闭集合。

sealed class Result {}

class Success extends Result {
  final String data;
  Success(this.data);
}

class Failure extends Result {
  final String error;
  Failure(this.error);
}

密封类的强大之处在于穷尽性检查。当你对密封类型使用 switch 时,编译器知道所有可能的子类型,并确保你处理了每一种:

String handleResult(Result result) {
  return switch (result) {
    Success(data: var d) => 'Got: $d',
    Failure(error: var e) => 'Error: $e',
  };
  // 不需要 default:编译器知道所有情况都已覆盖!
}

void main() {
  var success = Success('Hello');
  var failure = Failure('Not found');
  
  print(handleResult(success));  // Got: Hello
  print(handleResult(failure));  // Error: Not found
}

如果你向密封类添加新的子类型,编译器会标记所有未处理该子类型的 switch 语句。因此,密封类非常适合用于建模状态、结果,或任何具有固定变体集合的场景。与抽象类不同,密封类可以确保外部代码无法添加意料之外的子类型。

challenge icon

挑战

简单

让我们使用密封类来构建一个网络请求处理器!你将创建一个类型安全的系统,用来表示网络响应的不同状态,确保妥善处理每一种可能的结果。

你将把代码整理到两个文件中:

  • response.dart:创建一个密封类层次结构,用来表示网络响应的所有可能状态:
    • 创建一个名为 NetworkResponse 的密封类,作为所有响应类型的基类
    • 创建一个继承 NetworkResponse 的 Loading 类,其中包含一个 String message 字段(例如,"Fetching data...")
    • 创建一个继承 NetworkResponse 的 Success 类,其中包含一个 String data 字段和一个 int statusCode 字段
    • 创建一个继承 NetworkResponse 的 Error 类,其中包含一个 String errorMessage 字段和一个 int errorCode 字段
  • main.dart:导入响应文件,并创建一个使用 switch 表达式处理所有响应类型的函数:
    • 创建一个名为 handleResponse(NetworkResponse response) 的函数,返回值类型为 String
    • 使用带模式匹配的 switch 表达式处理每种情况:
      • 对于 Loading:返回 Status: [message]
      • 对于 Success:返回 Success ([statusCode]): [data]
      • 对于 Error:返回 Error ([errorCode]): [errorMessage]
    • 创建三个响应实例,并打印分别处理它们的结果:
      • 创建一个消息为 Please wait... 的 Loading
      • 创建一个数据为 User profile loaded、状态码为 200 的 Success
      • 创建一个错误消息为 Not found、错误码为 404 的 Error

密封类的优点在于,编译器会确保你处理每一种可能的响应类型,因此不需要默认情况!

预期输出:

Status: Please wait...
Success (200): User profile loaded
Error (404): Not found

亲手试试

import 'response.dart';

// TODO: 创建函数 handleResponse(NetworkResponse response)
// 返回一个 String
// 使用带模式匹配的 switch 表达式处理每种情况:
// - 对于 Loading:返回 "Status: [message]"
// - 对于 Success:返回 "Success ([statusCode]): [data]"
// - 对于 Error:返回 "Error ([errorCode]): [errorMessage]"

void main() {
  // TODO: 创建一个 Loading 实例,message 为 "Please wait..."
  
  // TODO: 创建一个 Success 实例,data 为 "User profile loaded",状态码为 200
  
  // TODO: 创建一个 Error 实例,错误消息为 "Not found",错误码为 404
  
  // TODO: 打印处理每个响应的结果
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: Dart 在线编译器