Ràng buộc kiểu tổng quát
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 67 trên 110.
Đôi khi, bạn cần một kiểu tổng quát có một số khả năng nhất định. Ví dụ, nếu muốn so sánh các phần tử hoặc truy cập các thuộc tính cụ thể, T không bị giới hạn sẽ không đảm bảo rằng những khả năng đó tồn tại. Ràng buộc kiểu tổng quát cho phép bạn giới hạn tham số kiểu ở những kiểu cụ thể hoặc các lớp con của chúng.
Dùng từ khóa extends để giới hạn một tham số kiểu:
class NumberBox<T extends num> {
T value;
NumberBox(this.value);
T doubled() => (value * 2) as T;
}
void main() {
var intBox = NumberBox<int>(5);
var doubleBox = NumberBox<double>(3.5);
print(intBox.doubled()); // 10
print(doubleBox.doubled()); // 7.0
// var stringBox = NumberBox<String>('hi'); // Lỗi!
}Vì T extends num, trình biên dịch biết value hỗ trợ các phép toán số học như phép nhân. Nếu không có ràng buộc này, lời gọi value * 2 sẽ thất bại.
Các ràng buộc cũng áp dụng cho hệ thống phân cấp lớp của riêng bạn:
abstract class Animal {
String get name;
}
class Dog extends Animal {
String get name => 'Dog';
}
class Shelter<T extends Animal> {
List<T> animals = [];
void add(T animal) => animals.add(animal);
void printNames() {
for (var animal in animals) {
print(animal.name); // An toàn: T đảm bảo 'name' tồn tại
}
}
}Các ràng buộc tổng quát kết hợp tính linh hoạt của kiểu tổng quát với sự an toàn khi biết những thao tác nào có thể thực hiện trên kiểu dữ liệu của bạn.
Thử thách
DễHãy xây dựng một máy tính thống kê chỉ hoạt động với các kiểu số! Bạn sẽ tạo một lớp tổng quát có ràng buộc, đảm bảo rằng lớp chỉ có thể dùng với các số, nhờ đó bạn có thể thực hiện các phép toán an toàn trên những giá trị đã lưu.
Bạn sẽ sắp xếp code thành hai tệp:
stats.dart: Tạo một lớp tổng quátStats<T extends num>để quản lý danh sách các giá trị số:- Một
List<T>có tênvaluesđể lưu các số - Một hàm khởi tạo để khởi tạo danh sách bằng các giá trị được cung cấp
- Một phương thức
sum()trả về tổng của tất cả giá trị dưới dạngnum - Một phương thức
min()trả về giá trị nhỏ nhất dưới dạngT - Một phương thức
max()trả về giá trị lớn nhất dưới dạngT - Một phương thức
printStats()hiển thị các số liệu thống kê theo định dạng dễ đọc
- Một
main.dart: Nhập tệp stats của bạn và minh họa lớp tổng quát có ràng buộc với các kiểu số khác nhau:- Tạo một
Stats<int>với các giá trị[10, 25, 5, 30, 15]rồi gọiprintStats() - In ra một dòng trống
- Tạo một
Stats<double>với các giá trị[3.5, 1.2, 4.8, 2.1]rồi gọiprintStats()
- Tạo một
Phương thức printStats() sẽ in ra ba dòng thể hiện tổng, giá trị nhỏ nhất và giá trị lớn nhất. Vì T extends num, bạn có thể an toàn dùng các toán tử so sánh và phép toán số học với những giá trị này. Điều này sẽ không thể thực hiện được với kiểu tổng quát không có ràng buộc.
Đầu ra dự kiến:
Sum: 85
Min: 5
Max: 30
Sum: 11.6
Min: 1.2
Max: 4.8Tự làm thử
import 'stats.dart';
void main() {
// TODO: Tạo Stats<int> với các giá trị [10, 25, 5, 30, 15]
// và gọi printStats()
// TODO: In ra một dòng trống
// TODO: Tạo Stats<double> với các giá trị [3.5, 1.2, 4.8, 2.1]
// và gọi printStats()
}
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