Hàm khởi tạo và kế thừa
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 41 trên 110.
Khi một lớp con (child class) kế thừa lớp cha, bạn phải gọi hàm khởi tạo (constructor) của lớp cha để khởi tạo đúng cách các trường kế thừa. Dart cung cấp nhiều cách linh hoạt để xử lý việc này thông qua danh sách khởi tạo (initializer list) bằng super.
Nếu lớp cha có hàm khởi tạo nhận tham số, lớp con phải gọi hàm đó một cách tường minh:
class Person {
String name;
int age;
Person(this.name, this.age);
}
class Student extends Person {
String school;
Student(String name, int age, this.school) : super(name, age);
}Dart 2.17 giới thiệu tham số super, một cú pháp gọn gàng hơn, chuyển tiếp tham số trực tiếp đến hàm khởi tạo của lớp cha:
class Student extends Person {
String school;
// super.name và super.age được truyền trực tiếp đến hàm khởi tạo (constructor) của Person
Student(super.name, super.age, this.school);
}Khi làm việc với các hàm khởi tạo có tên, bạn chỉ định hàm khởi tạo của lớp cha cần gọi:
class Employee extends Person {
String department;
Employee(super.name, super.age, this.department);
Employee.intern(String name, this.department) : super(name, 18);
}Quy tắc chính rất đơn giản: lớp cha phải được khởi tạo đầy đủ trước khi lớp con thêm các thuộc tính của riêng nó. Dù bạn dùng lời gọi super() truyền thống hay các tham số super mới hơn, Dart đều đảm bảo chuỗi kế thừa được tạo đúng cách từ lớp cha đến lớp con.
Thử thách
DễHãy xây dựng một hệ thống quản lý kho sản phẩm để minh họa cách hàm khởi tạo hoạt động với tính kế thừa. Bạn sẽ tạo một hệ thống phân cấp, trong đó các loại sản phẩm khác nhau kế thừa từ lớp sản phẩm cơ sở và cần được khởi tạo đúng cách thông qua hàm khởi tạo của lớp cha.
Bạn sẽ sắp xếp code vào hai tệp:
product.dart: Định nghĩa hệ thống phân cấp sản phẩm tại đây:- Một lớp
Productcó các thuộc tínhString namevàdouble price, một hàm khởi tạo nhận cả hai giá trị và một phương thứcinfo()in ra[name]: $[price] - Một lớp
Bookkế thừaProductvà bổ sung thuộc tínhString author. Dùng tham số super để chuyển tiếpnamevàpriceđến hàm khởi tạo của lớp cha - Một lớp
Electronicskế thừaProductvà bổ sung thuộc tínhint warranty(tính theo tháng). Dùng lời gọisuper()theo cách truyền thống trong danh sách khởi tạo để truyền các giá trị đến lớp cha
- Một lớp
main.dart: Nhập tệp sản phẩm và minh họa cả hai cách kế thừa hàm khởi tạo:- Tạo một
Bookcó tên'Dart Essentials', giá29.99và tác giả'Jane Smith' - Gọi phương thức
info()của đối tượng, rồi in raAuthor: [author] - In ra một dòng trống
- Tạo một
Electronicscó tên'Wireless Mouse', giá45.50và thời hạn bảo hành24 - Gọi phương thức
info()của đối tượng, rồi in raWarranty: [warranty] months
- Tạo một
Cả hai lớp con đều kế thừa phương thức info() từ Product mà không cần ghi đè phương thức này. Điểm khác biệt chính nằm ở cách chúng gọi hàm khởi tạo của lớp cha: Book dùng cú pháp tham số super gọn hơn, còn Electronics dùng cách truyền thống với super() trong danh sách khởi tạo.
Đầu ra dự kiến:
Dart Essentials: $29.99
Author: Jane Smith
Wireless Mouse: $45.5
Warranty: 24 monthsTự làm thử
import 'product.dart';
void main() {
// TODO: Tạo một Book với:
// - name: 'Dart Essentials'
// - price: 29.99
// - author: 'Jane Smith'
// TODO: Gọi phương thức info() của Book
// TODO: In ra "Author: [author]"
// TODO: In ra một dòng trống
// TODO: Tạo một Electronics với:
// - name: 'Wireless Mouse'
// - price: 45.50
// - warranty: 24
// TODO: Gọi phương thức info() của Electronics
// TODO: In ra "Warranty: [warranty] months"
}
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