Giới thiệu về an toàn với giá trị null
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 23 trên 110.
Một trong những nguyên nhân phổ biến nhất gây ra bug trong lập trình là cố dùng một giá trị không tồn tại. Trong Dart, trạng thái “không có giá trị” đặc biệt này được biểu thị bằng null. Tính năng an toàn null của Dart giúp bạn phát hiện những lỗi này trước cả khi code chạy.
Nếu không có tính năng an toàn với null, bất kỳ biến nào cũng có thể là null, dẫn đến sự cố khi chạy chương trình nếu bạn cố sử dụng biến đó:
// Trong các phiên bản Dart cũ (chưa có cơ chế an toàn với null)
String name; // Có thể là null!
print(name.length); // Chương trình gặp lỗi nếu name là nullKhi bật tính năng an toàn null (Dart 2.12 trở lên), trình biên dịch phân biệt các biến có thể chứa null với các biến không thể chứa giá trị này. Theo mặc định, các biến là không thể null, tức là chúng luôn phải chứa một giá trị hợp lệ:
String name = 'Alice'; // Phải có giá trị
print(name.length); // An toàn vì name không bao giờ là nullTrình biên dịch sẽ từ chối biên dịch code nếu một biến không thể nhận giá trị null có khả năng mang giá trị null. Nhờ vậy, lỗi được phát hiện trong lúc biên dịch thay vì khi chạy, giúp chương trình của bạn đáng tin cậy hơn. Trong các bài học tiếp theo, bạn sẽ học cách khai báo kiểu có thể nhận giá trị null khi thực sự cần và các toán tử Dart cung cấp để xử lý an toàn những giá trị có khả năng là null.
Thử thách
DễHãy cùng tạo một hệ thống danh thiếp liên hệ đơn giản để minh họa tầm quan trọng của các biến không nullable. Bạn sẽ tạo một hệ thống trong đó mọi liên hệ đều phải có thông tin hợp lệ, chắc chắn có sẵn.
Bạn sẽ sắp xếp code thành hai tệp:
contact.dart: Định nghĩa một lớpContactđại diện cho thông tin liên hệ của một người. Vì chúng ta đang dùng tính an toàn null, mọi trường đều phải có giá trị hợp lệ, không được thiếu dữ liệu! Lớp của bạn cần có:- Một
String firstNamecho tên của liên hệ - Một
String lastNamecho họ của liên hệ - Một
String emailcho địa chỉ email của liên hệ - Một
int phoneDigitscho số chữ số trong số điện thoại của họ - Một hàm khởi tạo nhận cả bốn giá trị
- Một getter
fullNametrả về tên và họ ghép lại, với một dấu cách ở giữa - Một phương thức
displayCard()in ra thông tin liên hệ
- Một
main.dart: Nhập lớp liên hệ và tạo hai liên hệ để minh họa rằng mọi trường đều chắc chắn có giá trị:- Tạo một liên hệ có tên
'Emma', họ'Wilson', email'emma@mail.com'và số chữ số điện thoại là10 - Tạo một liên hệ có tên
'James', họ'Brown', email'james@work.com'và số chữ số điện thoại là11 - Gọi
displayCard()trên từng liên hệ theo thứ tự liệt kê ở trên
- Tạo một liên hệ có tên
Phương thức displayCard() cần in ra theo đúng định dạng sau:
--- Contact Card ---
Name: [fullName]
Email: [email]
Phone digits: [phoneDigits]Hãy chú ý rằng mọi biến đều phải được khởi tạo bằng một giá trị thực, đây chính là tính an toàn null! Trình biên dịch đảm bảo rằng khi bạn truy cập fullName, email hoặc bất kỳ trường nào khác, trường đó luôn chứa dữ liệu hợp lệ.
Đầu ra mong đợi:
--- Contact Card ---
Name: Emma Wilson
Email: emma@mail.com
Phone digits: 10
--- Contact Card ---
Name: James Brown
Email: james@work.com
Phone digits: 11Tự làm thử
import 'contact.dart';
void main() {
// TODO: Tạo liên hệ đầu tiên với:
// - tên: 'Emma'
// - họ: 'Wilson'
// - email: 'emma@mail.com'
// - số chữ số của số điện thoại: 10
// TODO: Tạo liên hệ thứ hai với:
// - tên: 'James'
// - họ: 'Brown'
// - email: 'james@work.com'
// - số chữ số của số điện thoại: 11
// TODO: Gọi displayCard() trên từng liên hệ theo thứ tự
}
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