Menu
CoddyTech

Lớp sealed (Dart 3)

Thuộc phần Lập trình hướng đối tượng trong hành trình Dart của Coddy. Bài học 85 trên 110.

Dart 3 giới thiệu lớp sealed (sealed classes), giúp giới hạn những lớp nào có thể kế thừa hoặc triển khai chúng. Khi đánh dấu một lớp là sealed, chỉ những lớp trong cùng tệp mới có thể là kiểu con trực tiếp của lớp đó. Điều này tạo ra một tập hợp khép kín gồm các kiểu con đã biết.

sealed class Result {}

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

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

Sức mạnh của lớp sealed (sealed class) đến từ việc kiểm tra tính đầy đủ. Khi dùng switch với một kiểu sealed, trình biên dịch biết tất cả kiểu con có thể có và đảm bảo bạn xử lý từng kiểu:

String handleResult(Result result) {
  return switch (result) {
    Success(data: var d) => 'Got: $d',
    Failure(error: var e) => 'Error: $e',
  };
  // Không cần default vì trình biên dịch biết mọi trường hợp đều đã được xử lý!
}

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

Nếu bạn thêm một kiểu con mới vào lớp sealed, trình biên dịch sẽ báo lỗi ở mọi câu lệnh switch không xử lý kiểu con đó. Vì vậy, lớp sealed rất phù hợp để mô hình hóa trạng thái, kết quả hoặc bất kỳ tình huống nào có một tập hợp biến thể cố định. Khác với lớp trừu tượng, lớp sealed đảm bảo rằng không có code bên ngoài nào có thể thêm kiểu con ngoài dự kiến.

challenge icon

Thử thách

Dễ

Hãy xây dựng trình xử lý yêu cầu mạng bằng các lớp sealed! Bạn sẽ tạo một hệ thống an toàn về kiểu, mô hình hóa các trạng thái khác nhau của phản hồi mạng, đảm bảo mọi kết quả có thể xảy ra đều được xử lý đúng cách.

Bạn sẽ sắp xếp code vào hai tệp:

  • response.dart: Tạo hệ thống phân cấp lớp sealed đại diện cho mọi trạng thái có thể có của phản hồi mạng:
    • Một lớp sealed tên là NetworkResponse, làm lớp cơ sở cho mọi kiểu phản hồi
    • Một lớp Loading mở rộng NetworkResponse, có trường String message (ví dụ: "Fetching data...")
    • Một lớp Success mở rộng NetworkResponse, có trường String data và trường int statusCode
    • Một lớp Error mở rộng NetworkResponse, có trường String errorMessage và trường int errorCode
  • main.dart: Nhập tệp phản hồi của bạn và tạo một hàm xử lý mọi kiểu phản hồi bằng biểu thức switch:
    • Tạo hàm handleResponse(NetworkResponse response) trả về String
    • Dùng biểu thức switch kết hợp với so khớp mẫu để xử lý từng trường hợp:
      • Với Loading: trả về Status: [message]
      • Với Success: trả về Success ([statusCode]): [data]
      • Với Error: trả về Error ([errorCode]): [errorMessage]
    • Tạo ba đối tượng phản hồi và in ra kết quả xử lý từng đối tượng:
      • Một Loading có thông báo Please wait...
      • Một Success có dữ liệu User profile loaded và mã trạng thái 200
      • Một Error có thông báo lỗi Not found và mã lỗi 404

Điểm hay của các lớp sealed là trình biên dịch đảm bảo bạn xử lý mọi kiểu phản hồi có thể xảy ra, không cần trường hợp mặc định!

Đầu ra dự kiến:

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

Tự làm thử

import 'response.dart';

// TODO: Tạo hàm (function) handleResponse(NetworkResponse response)
// trả về một String
// Dùng biểu thức switch kết hợp khớp mẫu để xử lý từng trường hợp:
// - Với Loading: trả về "Status: [message]"
// - Với Success: trả về "Success ([statusCode]): [data]"
// - Với Error: trả về "Error ([errorCode]): [errorMessage]"

void main() {
  // TODO: Tạo một instance Loading với message "Please wait..."
  
  // TODO: Tạo một instance Success với data "User profile loaded" và mã trạng thái 200
  
  // TODO: Tạo một instance Error với error message "Not found" và mã lỗi 404
  
  // TODO: In ra kết quả xử lý từng response
}
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Trình biên dịch Dart online