Chương 1: Tổng quan về OOP

 Giới thiệu và ôn tập LT có cấu trúc/thủ tục  Lập trình hướng đối tượng (OOP)  Đối tượng và lớp trong OOP  Một số khái niệm khác trong OOP

pdf86 trang | Chia sẻ: lylyngoc | Lượt xem: 1673 | Lượt tải: 3download
Bạn đang xem trước 20 trang tài liệu Chương 1: Tổng quan về OOP, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
ĐH CÔNG NGHỆ THÔNG TIN Số tiết lý thuyết: 45 tiết Số tiết thực hành: 30 tiết 1 GVHD: Dương Khai Phong – Email khaiphong@gmail.com 2 Chương 1: Tổng quan về OOP Chương 2: Lớp & đối tượng Chương 3: Hàm và hàm đa năng trong OOP Chương 4: Đa năng hóa toán tử Chương 5: Sự kế thừa và tính đa hình  Nội dung môn học: 3 Chương 1: Tổng quan về OOP Chương 2: Lớp & đối tượng Chương 3: Hàm và hàm đa năng trong OOP Chương 4: Đa năng hóa toán tử Chương 5: Sự kế thừa và tính đa hình  Nội dung môn học: 4 Giới thiệu và ôn tập LT có cấu trúc/thủ tục  Lập trình hướng đối tượng (OOP) Đối tượng và lớp trong OOP Một số khái niệm khác trong OOP  Chương 1: Tổng quan về OOP 5 Giới thiệu và ôn tập LT có cấu trúc/thủ tục  Lập trình hướng đối tượng (OOP) Đối tượng và lớp trong OOP Một số khái niệm khác trong OOP  Chương 1: Tổng quan về OOP 6 Lập trình có cấu trúc/thủ tục  Chương 1: Tổng quan về OOP  Tổ chức chương trình thành các chương trình con (hàm).  Mỗi chương trình con đảm nhận xử lý một công việc nhỏ trong toàn bộ hệ thống.  Mỗi chương trình con này lại có thể chia nhỏ thành các chương trình con nhỏ hơn. Chương trình = Cấu trúc dữ liệu + Giải thuật 7 Lập trình có cấu trúc/thủ tục  Chương 1: Tổng quan về OOP  Các ngôn ngữ hỗ trợ : Pascal, C, ...  Sử dụng các lệnh có cấu trúc: for, do, while, if then else...  Chương trình là tập các hàm/thủ tục. Ví dụ: viết chương trình xuất bảng cửu chương include “stdio.h” // Khai báo thư viện void main(){ for (int i=2;i<10;i++) { for (int j=1;j<10;j++) printf ("%d*%d=%d",i,j,i*j); printf ("\n"); } } 8 Lập trình có cấu trúc/thủ tục  Chương 1: Tổng quan về OOP Ưu điểm:  Chương trình cục bộ hóa, dễ hiểu, dễ bảo trì hơn.  Dễ dàng tạo ra các thư viện phần mềm.  Nhược điểm:  Dữ liệu và mã xử lý là tách rời.  Người lập trình phải biết cấu trúc dữ liệu (vấn đề này một thời gian dài được coi là hiển nhiên).  Khi thay đổi cấu trúc dữ liệu thì mã xử lý (thuật toán) phải thay đổi theo.  Khó đảm bảo tính đúng đắn của dữ liệu.  Không tự động khởi tạo hay giải phóng dữ liệu động.  Không mô tả đầy đủ, trung thực hệ thống trong thực tế. 9 Các lưu ý quan trọng trong lập trình  Cấu trúc chương trình C  Các kiểu dữ liệu cơ bản  Nhập /xuất  Các cấu trúc điều khiển  Hàm  Các kiểu dữ liệu tập hợp: mảng, cấu trúc, con trỏ  Lưu trữ: tập tin…  ….  Chương 2: Lớp và đối tượng trong OOP  Cấu trúc chương trình C: Thông thường một chương trình C được bố trí thành 5 phần: 1. Khai báo thư viện 2. Khai báo hằng, biến, cấu trúc TOÀN CỤC 3. Khai báo hàm 4. Chương trình chính 5. Định nghĩa các hàm đã khai báo  Ví dụ: viết chương trình tính n! #incldue “stdio.h“ #incldue “conio.h“ int tinhGT(int n){ void main(){ int n,kq; printf("Nhap n:"); scanf("%d",&n) kq=tinhGT(n); printf("Giai thua %d = %d",n,kq); } // Định nghĩa hàm tính giai thừa int tinhGT(int n){ int kq=1; for (int i=1;i<=n;i++) kq=kq*i; return kq; } 10 Các lưu ý quan trọng trong lập trình  Cấu trúc chương trình C  Các kiểu dữ liệu cơ bản  Nhập /xuất  Các cấu trúc điều khiển  Hàm  Các kiểu dữ liệu tập hợp: mảng, cấu trúc, con trỏ  Lưu trữ: tập tin…  ….  Chương 2: Lớp và đối tượng trong OOP  Các kiểu dữ liệu cơ bản:  Nhập / Xuất:  printf / scanf  gets / puts  getch / putch KÝ TỰ SỐ NGUYÊN THỰC CHUỖI int: %d long: %ld float: %f double: %lf char: %c string: %s (nếu ngôn ngữ lập trình có hỗ trợ) 11 Các lưu ý quan trọng trong lập trình  Cấu trúc chương trình C  Các kiểu dữ liệu cơ bản  Nhập /xuất  Các cấu trúc điều khiển  Hàm  Các kiểu dữ liệu tập hợp: mảng, cấu trúc, con trỏ  Lưu trữ: tập tin…  ….  Chương 2: Lớp và đối tượng trong OOP  Các cấu trúc điều khiển:  Hàm:  Lưu ý: có 2 loại tham số là tham số đầu vào (tham trị) và tham số đầu ra (tham biến) LẶP ĐIỀU KIỆN ĐIỀU KIỆN RẼ NHÁNH IF IF..ELSE SWITCH..CASE FOR WHILE DO..WHILE Tên_Hàm(DS_Tham số) { // Định nghĩa hàm return } 12 Các lưu ý quan trọng trong lập trình  Cấu trúc chương trình C  Các kiểu dữ liệu cơ bản  Nhập /xuất  Các cấu trúc điều khiển  Hàm  Các kiểu dữ liệu tập hợp: mảng, cấu trúc, con trỏ  Lưu trữ: tập tin…  ….  Chương 2: Lớp và đối tượng trong OOP  Mảng:  Khái niệm  Khai báo  Sử dụng  Các bài toán liên quan: tìm kiếm, sắp xếp,…  Cấu trúc:  Khái niệm  Khai báo  Sử dụng  Các bài toán liên quan  Con trỏ:  Khái niệm  Khai báo  Sử dụng  Mối quan hệ: mảng, cỏn trỏ và cấu trúc. ĐH CÔNG NGHỆ THÔNG TIN 13 ĐH CÔNG NGHỆ THÔNG TIN 14 15  Bài tập chương 1 – Phần lập trình có cấu trúc/thủ tục: Buổi 1 1. Viết chương trình nhập dài (height), rộng (width). Tính chu vi P và diện tích S của hình chữ nhật. 2. Viết chương trình nhập 3 cạnh tam giác a,b,c. Tính P và S của tam giác. S = 𝑝 ∗ 𝑝 − 𝑎 ∗ 𝑝 − 𝑏 ∗ (𝑝 − 𝑐) 3. Viết chương trình kiểm tra một số nguyên nhập từ bàn phím có phải là số nguyên tố hay không? 4. Viết chương trình kiểm tra ngày tháng năm có hợp lệ hay không? 5. Viết chương trình cộng, trừ hai phân số. 16 Giới thiệu và ôn tập LT có cấu trúc/thủ tục  Lập trình hướng đối tượng (OOP) Đối tượng và lớp trong OOP Một số khái niệm khác trong OOP  Chương 1: Tổng quan về OOP 17 Lập trình hướng đối tượng (OOP)  Chương 1: Tổng quan về OOP  Lập trình hướng đối tượng (Object Oriented Programming - LTHĐT) là phương pháp lập trình lấy đối tượng làm nền tảng để xây dựng thuật giải, xây dựng chương trình Đối tượng là gi? 18 Giới thiệu và ôn tập LT có cấu trúc/thủ tục  Lập trình hướng đối tượng (OOP) Đối tượng và lớp trong OOP Một số khái niệm khác trong OOP  Chương 1: Tổng quan về OOP 19 Đối tượng và lớp trong OOP  Chương 1: Tổng quan về OOP • Đối tượng (object): – Khái niệm đối tượng trong thế giới thực được hiểu như là một thực thể: người, vật hoặc một bảng dữ liệu… – Đối tượng phục vụ hai mục đích: giúp hiểu rõ thế giới thực và cung cấp cơ sở cho việc cài đặt trên máy tính. – Mỗi đối tượng có một nét nhận dạng, thuộc tính để phân biệt với các đối tượng khác – Ví dụ: - Đối tượng Sinh viên , Nhân viên - Đối tượng thời gian 20 Đối tượng và lớp trong OOP  Chương 1: Tổng quan về OOP • Lớp: (class) – Các đối tượng có các đặc tính tương tự nhau được gom chung lại thành lớp đối tượng. Ví dụ Người là một lớp đối tượng. Một lớp đối tượng được đặc trưng bằng các thuộc tính và các hoạt động (hành vi,thao tác). – Một thuộc tính (attribute): là một giá trị dữ liệu cho mỗi đối tượng trong lớp. (Ví dụ:Tên, Tuổi, Cân nặng là các thuộc tính của Người) – Một thao tác (operation): là một hàm hay một phép biến đổi có thể áp dụng vào hay áp dụng bởi các đối tượng trong lớp. 21 Giới thiệu và ôn tập LT có cấu trúc/thủ tục  Lập trình hướng đối tượng (OOP) Đối tượng và lớp trong OOP Một số khái niệm khác trong OOP  Chương 1: Tổng quan về OOP 22 Một số khái niệm khác trong OOP  Chương 1: Tổng quan về OOP  Phương thức (method)  Thể hiện (instance)  Sơ đồ đối tượng  Tính đa hình (polymorphism)  Tính thừa kế (inheritance)  Tính đóng gói (encapsulation) … 23 Một số khái niệm khác trong OOP  Chương 1: Tổng quan về OOP  Phương thức (method)  Thể hiện (instance)  Sơ đồ đối tượng  Tính đa hình (polymorphism)  Tính thừa kế (inheritance)  Tính đóng gói (encapsulation) …  Phương thức (method) Mỗi thao tác trên một lớp đối tượng cụ thể tương ứng với một cài đặt cụ thể khác nhau. Một cài đặt như vậy được gọi là một phương thức (method). 24 Một số khái niệm khác trong OOP  Chương 1: Tổng quan về OOP  Phương thức (method)  Thể hiện (instance)  Sơ đồ đối tượng  Tính đa hình (polymorphism)  Tính thừa kế (inheritance)  Tính đóng gói (encapsulation) …  Thể hiện (instance) Một đối tượng cụ thể thuộc một lớp được gọi là một thể hiện (instance) của lớp đó. Ví dụ: Joe Smith, 25 tuổi, nặng 58kg.. là một thể hiện của lớp người. 25 Một số khái niệm khác trong OOP  Chương 1: Tổng quan về OOP  Phương thức (method)  Thể hiện (instance)  Sơ đồ đối tượng  Tính đa hình (polymorphism)  Tính thừa kế (inheritance)  Tính đóng gói (encapsulation) … 26 Một số khái niệm khác trong OOP  Chương 1: Tổng quan về OOP  Phương thức (method)  Thể hiện (instance)  Sơ đồ đối tượng  Tính đa hình (polymorphism)  Tính thừa kế (inheritance)  Tính đóng gói (encapsulation) …  Sơ đồ đối tượng:  Là sơ đồ dùng để mô tả lớp đối tượng. Sơ đồ đối tượng bao gồm sơ đồ lớp và sơ đồ thể hiện.  Sơ đồ lớp: mô tả các lớp đối tượng trong hệ thống. Một lớp đối tượng được diễn tả bằng một hình chữ nhật có 3 phần:  Phần đầu chỉ tên lớp.  Phần thứ hai mô tả các thuộc tính.  Phần thứ ba mô tả các thao tác của các đối tượng trong lớp đó. Sinh viên Họ tên Năm sinh Mã số Điểm TB Đi học Đi thi Xếp loại Thuộc tính Thao tác Tên lớp Sơ đồ lớp Sinh viên Nguyễn Văn A 1984 0610234T 9.2 Sơ đồ thể hiện 27 Một số khái niệm khác trong OOP  Chương 1: Tổng quan về OOP  Phương thức (method)  Thể hiện (instance)  Sơ đồ đối tượng  Tính đa hình (polymorphism)  Tính thừa kế (inheritance)  Tính đóng gói (encapsulation) …  Tính đa hình (polymorphism) Là cách thức truy cập các hàm khác nhau tùy thuộc vào đối tượng mà con trỏ đang trỏ tới khi ta thực thi cùng một lời gọi hàm. Ví dụ: Đối với nhân viên trong cùng một công ty nhưng cách tính lương của nhân viên văn phòng khác cách tính lương của nhân viên sản xuất. 28 Một số khái niệm khác trong OOP  Chương 1: Tổng quan về OOP  Phương thức (method)  Thể hiện (instance)  Sơ đồ đối tượng  Tính đa hình (polymorphism)  Tính thừa kế (inheritance)  Tính đóng gói (encapsulation) …  Tính thừa kế (inheritance) Là sự tái sử dụng các lớp có các đặc tính chung với nhau để tạo ra các lớp mới từ một hay nhiều lớp đã có. Ví dụ: Đối Xét về bản chất: NV_VP và NV_SX đều là nhân viên nên nó phải có các thuộc tính chung: MaNV, Hoten, CMND.. của một ngưởi nhân viên => kế thừa từ lớp NV. 29 Một số khái niệm khác trong OOP  Chương 1: Tổng quan về OOP  Phương thức (method)  Thể hiện (instance)  Sơ đồ đối tượng  Tính đa hình (polymorphism)  Tính thừa kế (inheritance)  Tính đóng gói (encapsulation) …  Tính đóng gói (encapsulation) Là cơ chế ràng buộc dữ liệu và thao tác trên dữ liệu đó thành một thể thống nhất, tránh được các tác động bất ngờ từ bên ngoài. Ví dụ: Một lớp có thể có nhiều thuộc tính và hàm. Ta có thể xét quyền truy cập cho các thuộc tính và hàm này. … 30 Chương 1: Tổng quan về OOP Chương 2: Lớp & đối tượng Chương 3: Hàm và hàm đa năng trong OOP Chương 4: Đa năng hóa toán tử Chương 5: Sự kế thừa và tính đa hình  Nội dung môn học: 31 Khai báo lớp, đối tượng  Từ khoá xác định thuộc tính truy xuất Con trỏ this  Phép gán đối tượng Hàm thiết lập (Constructor) Hàm hủy (Destructor) Các lưu ý quan trọng trong OOP  Chương 2: Lớp & đối tượng  Chương 2: Lớp và đối tượng trong OOP 32 Khai báo lớp, đối tượng  Từ khoá xác định thuộc tính truy xuất Con trỏ this  Phép gán đối tượng Hàm thiết lập (Constructor) Hàm hủy (Destructor) Các lưu ý quan trọng trong OOP  Chương 2: Lớp & đối tượng  Chương 2: Lớp và đối tượng trong OOP 33 Khai báo lớp, đối tượng  Lớp là gì? Đối tượng là gì?  Cú pháp khai báo lớp:  Chương 2: Lớp và đối tượng trong OOP class { private: public: }; <định nghĩa của các hàm thành phần chưa được định nghĩa bên trong khai báo lớp> Lưu ý cuối lớp phải có dấu “;” 34 Khai báo lớp, đối tượng  Ví dụ: khai báo lớp HINHCHUNHAT  Chương 2: Lớp và đối tượng trong OOP class HINHCHUNHAT{ private: int dai,rong; public: void nhap(); void xuat(); int tinhS(); }; 35 Khai báo lớp, đối tượng  Định nghĩa các hàm thành phần ở bên ngoài khai báo lớp:  Chương 2: Lớp và đối tượng trong OOP :: ([danh sách tham số] ) { [nội dung] [return giá_trị_nếu có;] }  Tạo đối tượng:  Gọi hàm thành phần của lớp: . (); Toán tử phạm vi 36 Khai báo lớp, đối tượng  Ví dụ: khai báo và định nghĩa lớp HINHCHUNHAT  Chương 2: Lớp và đối tượng trong OOP class HCN{ private: int dai,rong; public: void nhap(); void xuat(); int tinhS(); }; // Định nghĩa các hàm void HCN::nhap() { printf("Nhap dai:"); scanf("%d",&dai); printf("Nhap rong:"); scanf("%d",&rong); } int HCN::tinhS() { return dai*rong; } 37 Khai báo lớp, đối tượng  Ví dụ: sử dụng lớp HINHCHUNHAT  Chương 2: Lớp và đối tượng trong OOP class HCN{ private: int dai,rong; public: void nhap(); void xuat(); int tinhS(); }; // Định nghĩa các hàm void HCN::nhap() { printf("Nhap dai:"); scanf("%d",&dai); printf("Nhap rong:"); scanf("%d",&rong); } void HCN::xuat() { printf("Dai = %d",dai); printf("Rong = %d",rong); } int HCN::tinhS() { return dai*rong; } // Sử dụng lớp void main() { HCN s; s.nhap(); s.xuat(); printf("Dien tich = %d",s.tinhS()); } 38 Khai báo lớp, đối tượng  Từ khoá xác định thuộc tính truy xuất Con trỏ this  Phép gán đối tượng Hàm thiết lập (Constructor) Hàm hủy (Destructor) Các lưu ý quan trọng trong OOP  Chương 2: Lớp & đối tượng  Chương 2: Lớp và đối tượng trong OOP 39 Từ khoá xác định thuộc tính truy xuất  Từ khoá là gì? Truy xuất là gì?  Ví dụ:  Chương 2: Lớp và đối tượng trong OOP class { private: … public: …. }; Từ khoá xác định thuộc tính truy xuất  Đặc điểm: Trong lớp có thể có nhiều nhãn private và private. Mỗi nhãn này có phạm vi ảnh hưởng cho đến khi gặp một nhãn kế tiếp hoặc hết khai báo lớp. Nhãn private đầu tiên có thể bỏ đi vì C++ ngầm hiểu rằng các thành phần trước nhãn public đầu tiên là private. 40 Từ khoá xác định thuộc tính truy xuất  Ý nghĩa của các từ khoá truy xuất: các từ khoá này xác định khả năng truy xuất thành phần (thuộc tính, phương thức) của một lớp.  private: những thành phần được liệt kê bên trong phần private chỉ được truy xuất bên trong phạm vi lớp và không được phép kế thừa.  public: những thành phần được liệt kê bên trong phần public được truy xuất từ bất kỳ phạm vi nào và được kế thừa lại trong lớp dẫn xuất (kế thừa).  protected: những thành phần được liệt kê bên trong phần protected được truy xuất từ bên trong phạm vi lớp,từ lớp dẫn xuất (kế thừa) và được kế thừa lại trong lớp dẫn xuất (kế thừa).  Chương 2: Lớp và đối tượng trong OOP 41 Từ khoá xác định thuộc tính truy xuất  Ví dụ về từ khoá truy xuất:  Chương 2: Lớp và đối tượng trong OOP class ABC{ private: int x; public: int y; public: void xuat(); }; // Định nghĩa các hàm void ABC::xuat() { printf("%d",x); printf("%d",y); } class TEST: public ABC{ private: int z; public: void in(); }; // Định nghĩa các hàm void TEST::in() { printf("%d",x); printf("%d",y); printf("%d",z); } void main(){ ABC a; TEST b; a.x = 5; a.y = 10 a.xuat(); b.x = 10; b.y = 15; b.z = 20; b.in(); } Trong phạm vi lớp Từ lớp dẫn xuất Bên ngoài lớp // OK // OK // OK // OK // OK // OK 42 Khai báo lớp, đối tượng  Từ khoá xác định thuộc tính truy xuất Con trỏ this  Phép gán đối tượng Hàm thiết lập (Constructor) Hàm hủy (Destructor) Các lưu ý quan trọng trong OOP  Chương 2: Lớp & đối tượng  Chương 2: Lớp và đối tượng trong OOP 43 Con trỏ this  Con trỏ là gì?  Con trỏ this được dùng để tham chiếu đến chính địa chỉ của đối tượng của lớp.  Dùng toán tử -> để truy cập đến các thành viên của đối tượng.  Công dụng:  Giúp ta truy cập, phân biệt được các thành viên ngay bên trong lớp.  Khi hàm thành viên cần trả giá trị về là chính đối tượng.  Chương 2: Lớp và đối tượng trong OOP class Person{ private: int age; public: void display(int age); Person getPerson(); }; // Định nghĩa các hàm void Person::display(int age) { age = 25; this->age = 30; } Person Person::getPerson() { return *this; // trả về chính đối tượng } 44 Khai báo lớp, đối tượng  Từ khoá xác định thuộc tính truy xuất Con trỏ this  Phép gán đối tượng Hàm thiết lập (Constructor) Hàm hủy (Destructor) Các lưu ý quan trọng trong OOP  Chương 2: Lớp & đối tượng  Chương 2: Lớp và đối tượng trong OOP 45  Phép gán đối tượng  Phép gán là gì?  Trong OOP, phép gán đối tượng là việc sao chép các giá trị của các thành phần dữ liệu từ đối tượng a sang đối tượng b.  Chương 2: Lớp và đối tượng trong OOP class Person{ private: int tuoi,CMND; public: void khoitao(int t, int c); }; void Person::khoitao(int t, int c) { tuoi = t; CMND = c; } void main() { Person a; a.khoitao(28,123456); Person b; b = a; } Per son a tuoi CMND 28 123456 Per son b tuoi CMND 28 123456 46 Khai báo lớp, đối tượng  Từ khoá xác định thuộc tính truy xuất Con trỏ this  Phép gán đối tượng Hàm thiết lập (Constructor) Hàm hủy (Destructor) Các lưu ý quan trọng trong OOP  Chương 2: Lớp & đối tượng  Chương 2: Lớp và đối tượng trong OOP 47 Hàm thiết lập (Constructor)  Constructor là một loại phương thức đặc biệt dùng để khởi tạo thể hiện của lớp một cách tự động.  Bất kể loại cấp phát bộ nhớ nào được sử dụng (tự động, tĩnh, động), mỗi khi một thể hiện của lớp được tạo, một hàm constructor nào đó của lớp sẽ được gọi.  Một lớp không có khai báo bất kỳ hàm thiết lập nào thì hàm thiết lập không đối số được tạo ra mặc định.  Đặc điểm của hàm thiết lập (khởi tạo): – Constructor có cùng tên với tên của lớp – Constructor không có giá trị trả về (kể cả void) – Constructor phải có thuộc tính public – Constructor có thể được khai báo chồng như các hàm C++ thông thường khác. – Constructor có thể được khai báo với các tham số có giá trị ngầm định.  Chương 2: Lớp và đối tượng trong OOP 48  Ví dụ về hàm thiết lập:  Chương 2: Lớp và đối tượng trong OOP class HCN{ private: int dai,rong; public: HCN(); HCN(int d,int r); HCN(int d=10,int r=10); void nhap(); void xuat(); }; // Hàm khởi tạo không đối số // Hàm khởi tạo hai đối số // Hàm khởi tạo đối số được gán giá trị ngầm định Lưu ý: ta có thể định nghĩa các hàm khởi tạo ngay bên trong việc khai báo lớp hoặc định nghĩa bên ngoài lớp. Hàm thiết lập (Constructor) 49 Khai báo lớp, đối tượng  Từ khoá xác định thuộc tính truy xuất Con trỏ this  Phép gán đối tượng Hàm thiết lập (Constructor) Hàm hủy (Destructor) Các lưu ý quan trọng trong OOP  Chương 2: Lớp & đối tượng  Chương 2: Lớp và đối tượng trong OOP 50 Hàm hủy (Destructor)  Destructor cũng như phương thức constructor (được gọi khi một đối tượng được tạo), loại phương thức thứ hai là destructor, được gọi ngay trước khi thu hồi một đối tượng.  Destructor thường được dùng để thực hiện mọi việc dọn dẹp cần thiết trước khi một đối tượng bị huỷ.  Đặc điểm của hàm huỷ (destructor): – Destructor có cùng tên với tên của lớp nhưng bắt đầu dấu ~ – Destructor không có giá trị trả về (kể cả void) – Destructor phải có thuộc tính public – Destructor không có các tham số  Chương 2: Lớp và đối tượng trong OOP 51  Ví dụ về hàm huỷ:  Chương 2: Lớp và đối tượng trong OOP class HCN{ private: int dai,rong
Tài liệu liên quan