Trường final và const
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 18 trên 110.
Khi khai báo các trường trong một lớp, bạn có thể dùng final hoặc const để kiểm soát việc giá trị có thể thay đổi sau khi khởi tạo hay không. Cả hai đều tạo ra các giá trị bất biến, nhưng chúng hoạt động khác nhau.
Trường final chỉ có thể được gán một lần, nhưng giá trị của nó được xác định khi chạy chương trình. Bạn có thể gán giá trị trong phần khai báo hoặc thông qua hàm khởi tạo:
class Person {
final String name;
final DateTime createdAt = DateTime.now();
Person(this.name);
}
Person p = Person('Alice');
// p.name = 'Bob'; // Lỗi: không thể gán lại giá trị cho trường finalname được thiết lập khi đối tượng được tạo, còn createdAt ghi lại thời điểm hiện tại. Cả hai giá trị đều bị khóa sau khi khởi tạo.
Trường static const phải có giá trị xác định được tại thời điểm biên dịch. Trường này thuộc về chính lớp và được dùng chung cho mọi đối tượng:
class Circle {
static const double pi = 3.14159;
final double radius;
Circle(this.radius);
double get area => Circle.pi * radius * radius;
}Điểm khác biệt chính: các thuộc tính final có thể chứa giá trị được tính khi chạy (như DateTime.now()), còn const yêu cầu hằng số tại thời điểm biên dịch. Thuộc tính instance không thể trực tiếp là const, chỉ có thể dùng static const ở cấp lớp.
Thử thách
DễHãy xây dựng một hệ thống danh mục sản phẩm để minh họa sự khác biệt giữa các trường final và static const. Bạn sẽ tạo các sản phẩm có thuộc tính bất biến và các giá trị cấu hình dùng chung.
Bạn sẽ sắp xếp code thành hai tệp:
product.dart: Định nghĩa một lớpProductđại diện cho một mặt hàng trong cửa hàng. Lớp của bạn cần có:- Một
static const double taxRatecó giá trị0.08(thuế suất 8% dùng chung cho tất cả sản phẩm) - Một
static const String currencycó giá trị'USD' - Một
final String namelưu tên sản phẩm (được thiết lập qua hàm khởi tạo) - Một
final double basePricelưu giá gốc của sản phẩm (được thiết lập qua hàm khởi tạo) - Một
final String sku(đơn vị lưu kho), kết hợp tiền tố với tên sản phẩm, được tính trong danh sách khởi tạo bằng cách thêm tên viết hoa vào sau'SKU-' - Một hàm khởi tạo nhận
namevàbasePrice - Một getter
priceWithTaxtính giá đã bao gồm thuế - Một phương thức
display()in thông tin sản phẩm ra
- Một
main.dart: Nhập lớp sản phẩm và tạo hai sản phẩm:- Một sản phẩm
'Laptop'có giá gốc là999.99 - Một sản phẩm
'Mouse'có giá gốc là29.99
display()cho từng sản phẩm theo thứ tự liệt kê ở trên.- Một sản phẩm
Phương thức display() cần in ra theo đúng định dạng sau:
[sku] - [name]: [basePrice] [currency] (with tax: [priceWithTax] [currency])Khi hiển thị, làm tròn priceWithTax đến 2 chữ số thập phân bằng toStringAsFixed(2).
Kết quả mong đợi:
SKU-LAPTOP - Laptop: 999.99 USD (with tax: 1079.99 USD)
SKU-MOUSE - Mouse: 29.99 USD (with tax: 32.39 USD)Tự làm thử
import 'product.dart';
void main() {
// TODO: Tạo một Product tên là 'Laptop' với giá cơ bản 999.99
// TODO: Tạo một Product tên là 'Mouse' với giá cơ bản 29.99
// TODO: Gọi display() cho từng sản phẩm theo thứ tự (Laptop trước, rồi đến Mouse)
}
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
1Nền tảng về lập trình hướng đối tượng
Tệp bên ngoàiThư viện và câu lệnh importGiới thiệu về lập trình hướng đối tượngLớp và đối tượngTừ khóa thisPhương thứcBiến thể hiệnKiến thức cơ bản về hàm khởi tạoÔn tập: Máy tính đơn giản4An toàn với giá trị null
Giới thiệu về an toàn với giá trị nullCó thể null và không thể nullToán tử ? và !Từ khóa late và an toàn với giá trị nullToán tử xử lý nullAn toàn với giá trị null trong lớpÔn tập: hệ thống hồ sơ người dùng7Lớp trừu tượng và interface
Lớp trừu tượngPhương thức trừu tượngInterface trong DartInterface ngầm địnhTriển khai và kế thừaNhiều interfaceÔn tập: Máy tính hình10Bộ sưu tập và kiểu tổng quát
Tổng quan về List, Set và MapBộ sưu tập an toàn về kiểuLớp tổng quátPhương thức tổng quátRàng buộc kiểu tổng quátIterable và IteratorÔn tập: Lưu trữ tổng quát2Hàm khởi tạo trong Dart
Hàm khởi tạo mặc địnhHàm khởi tạo có tênDanh sách khởi tạoHàm khởi tạo hằng sốHàm khởi tạo nhà máyHàm khởi tạo chuyển hướngÔn tập: Trình tạo hình dạng5Đóng gói
Thành viên công khai và riêng tưQuy ước tiền tố _Tính riêng tư ở cấp thư việnTìm hiểu sâu về getter và setterChe giấu thông tinÔn tập: hồ sơ học sinh8Mixin
Giới thiệu về MixinTạo MixinSử dụng nhiều MixinTừ khóa on trong MixinMixin và kế thừaMixin và giao diệnÔn tập: hệ thống động vật3Thuộc tính của lớp
Thành viên instance và thành viên tĩnhTrường final và constBiến latePhương thức và trường tĩnhGetter và setterÔn tập: trình quản lý tài khoản ngân hàng6Kế thừa
Kế thừa cơ bảnTừ khóa superGhi đè phương thứcChú thích @overrideTừ khóa lớp finalHàm khởi tạo và kế thừaÔn tập: phân cấp nhân viên9Đa hình
Khái niệm cơ bản về đa hìnhĐa hình qua giao diệnKiểm tra kiểu lúc chạyToán tử is và asTừ khóa hiệp biếnÔn tập: Bộ xử lý thanh toánTự luyện tập: Trình biên dịch Dart online