Menu
CoddyTech

Từ khóa lớp final

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 40 trên 110.

Đôi khi bạn muốn ngăn một lớp (class) bị mở rộng. Từ khóa (keyword) final, khi áp dụng cho một lớp, sẽ ngăn mọi lớp khác kế thừa từ lớp đó.

final class DatabaseConnection {
  String connectionString;
  
  DatabaseConnection(this.connectionString);
  
  void connect() {
    print('Connected to $connectionString');
  }
}

// Điều này sẽ gây ra lỗi khi biên dịch:
// class CustomConnection extends DatabaseConnection { }

Đánh dấu một lớp là final rất hữu ích khi việc mở rộng lớp đó có thể phá vỡ hành vi dự kiến hoặc các đảm bảo bảo mật. Ví dụ, một lớp quản lý tài nguyên nhạy cảm có thể cần đảm bảo rằng các phương thức của nó không bị ghi đè theo những cách ngoài dự kiến.

Dart 3 cũng giới thiệu các từ bổ nghĩa liên quan: base buộc các lớp con phải dùng extends (không dùng implements), còn sealed giới hạn việc kế thừa trong cùng một thư viện. Trước mắt, hãy tập trung vào final, cách đơn giản nhất để khóa hoàn toàn một lớp.

Dùng các lớp final khi bạn chắc chắn thiết kế lớp đã hoàn chỉnh và việc kế thừa chỉ gây ra vấn đề. Tuy nhiên, đừng dùng quá nhiều, vì hầu hết các lớp đều có lợi khi vẫn cho phép mở rộng.

challenge icon

Thử thách

Dễ

Hãy xây dựng một hệ thống cấu hình an toàn để minh họa khi nào và vì sao bạn nên ngăn một lớp được mở rộng. Bạn sẽ tạo một lớp final để quản lý các thiết lập ứng dụng, đảm bảo hành vi của lớp không thể bị thay đổi thông qua tính kế thừa.

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

  • config.dart: Định nghĩa các lớp cấu hình tại đây:
    • Một final class AppConfig không thể được mở rộng. Lớp này cần có thuộc tính String appName và String version, một hàm khởi tạo nhận cả hai giá trị, cùng phương thức display() để in ra [appName] v[version]
    • Một lớp Feature thông thường (không phải final), có thuộc tính String name và bool enabled, một hàm khởi tạo nhận cả hai giá trị, cùng phương thức status() để in ra [name]: [enabled ? 'ON' : 'OFF']
    • Một lớp ExperimentalFeature kế thừa Feature và bổ sung thuộc tính String warning. Ghi đè status() bằng @override để gọi phiên bản của lớp cha trước bằng super.status(), sau đó in ra Warning: [warning]
  • main.dart: Nhập tệp cấu hình và minh họa sự khác biệt giữa lớp final và lớp thông thường:
    • Tạo một AppConfig với appName là 'MyApp' và version là '2.0.1', sau đó gọi display()
    • In ra một dòng trống
    • Tạo một Feature có name là 'Dark Mode' và enabled là true, sau đó gọi status()
    • In ra một dòng trống
    • Tạo một ExperimentalFeature có name là 'AI Assistant', enabled là false và warning là 'May be unstable', sau đó gọi status()

Hãy chú ý rằng AppConfig được khai báo là final vì hành vi cấu hình của lớp này cần luôn nhất quán và an toàn. Không lớp con nào có thể thay đổi cách quản lý các thiết lập. Trong khi đó, Feature vẫn có thể được mở rộng, cho phép ExperimentalFeature bổ sung hành vi chuyên biệt.

Đầu ra dự kiến:

MyApp v2.0.1

Dark Mode: ON

AI Assistant: OFF
Warning: May be unstable

Tự làm thử

import 'config.dart';

void main() {
  // TODO: Tạo một AppConfig với appName là 'MyApp' và version là '2.0.1'
  // Sau đó gọi display()
  
  // TODO: In ra một dòng trống
  
  // TODO: Tạo một Feature với name là 'Dark Mode' và enabled là true
  // Sau đó gọi status()
  
  // TODO: In ra một dòng trống
  
  // TODO: Tạo một ExperimentalFeature với name là 'AI Assistant',
  // enabled là false và warning là 'May be unstable'
  // Sau đó gọi status()
}
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