Bài giảng Lập trình hướng đối tượng - Ôn tập tốt nghiệp - Chương 1: Đối tượng và lớp

Giới thiệu • Phân tích thiết kế và lập trình theo hướng đối tượng tuy sinh sau đẻ muộn nhưng đã chứng tỏ được những ưu điểm vượt trội so với cách tiếp cận cổ điển. Trong lĩnh vực phân tích và thiết kế hệ thống, hướng tiếp cận mới mẻ này đã thu hút nhiều nhà nghiên cứu tên tuổi. Nhiều kiểu mẫu, phương pháp luận, mô hình phân tích đã được đưa ra với những mức độ thành công khác nhau. Ta sẽ nghiên cứu phương hướng phân tích theo quan điểm của Rumbaugh: Mô hình hoá và thiết kế theo hướng đối tượng. Phương pháp phân tích bằng mô hình, Phân tích dựa trên CƠ SỞ mô hình hóa các đối tượng trong thế giới thực. Dùng mô hình để xây dựng một thiết kế không phụ thuộc ngôn ngữ được tổ chức xung quanh các đối tượng. So với cách tổ chức cổ điển, mô hình hoá và thiết kế hướng đối tượng giúp hiểu rõ hơn yêu cầu của vấn đề, thiết kế trong sáng hơn, và kết quả là những hệ thống dễ dàng bảo trì hơn.

pdf118 trang | Chia sẻ: candy98 | Lượt xem: 467 | Lượt tải: 0download
Bạn đang xem trước 20 trang tài liệu Bài giảng Lập trình hướng đối tượng - Ôn tập tốt nghiệp - Chương 1: Đối tượng và lớp, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
Lập Trình Hướng Đối Tượng Ôn tập tốt nghiệp Chương 1 Đối tượng và lớp Giới thiệu  Phân tích thiết kế và lập trình theo hướng đối tượng tuy sinh sau đẻ muộn nhưng đã chứng tỏ được những ưu điểm vượt trội so với cách tiếp cận cổ điển.  Trong lãnh vực phân tích và thiết kế hệ thống, hướng tiếp cận mới mẻ này đã thu hút nhiều nhà nghiên cứu tên tuổi. Nhiều kiểu mẫu, phương pháp luận, mô hình phân tích đã được đưa ra với những mức độ thành công khác nhau. Ta sẽ nghiên cứu phương hướng phân tích theo quan điểm của Chương 2- Lớp và đối tượng 3  Rumbaugh: Mô hình hoá và thiết kế theo hướng đối tượng. Phương pháp phân tích bằng mô hình  Phân tích dựa trên cơ sở mô hình hóa các đối tượng trong thế giới thực.  Dùng mô hình để xây dựng một thiết kế không phụ thuộc ngôn ngữ được tổ chức xung quanh các đối tượng.  So với cách tổ chức cổ điển, mô hình hoá và thiết kế hướng đối tượng giúp hiểu rõ hơn yêu cầu của vấn đề, Chương 2- Lớp và đối tượng 4 thiết kế trong sáng hơn, và kết quả là những hệ thống dễ dàng bảo trì hơn. Phương pháp phân tích bằng mô hình  Các khái niệm trong thế giới thực được mô hình hoá bằng các ký hiệu đồ hoạ mô tả các đối tượng của chúng (cấu trúc dữ liệu và hành vi) độc lập với ngôn ngữ.  Các khái niệm và ký hiệu này có thể được dùng thống nhất suốt quá trình phát triển hệ thống từ phân tích, thiết kế đến cài đặt mà không cần thay đổi qua các giai đoạn như một số phương pháp luận khác. Chương 2- Lớp và đối tượng 5  Không quan tâm đến chi tiết cài đặt cho đến giai đoạn cuối của qui trình phát triển hệ thống. Phương pháp phân tích bằng mô hình  Các khái niệm liên quan đến máy tính chỉ được đưa ra ở bước mã hóa sau cùng, nhờ đó giữ được sự uyển chuyển, linh động và có được tự do quyết định trong giai đoạn phân tích và thiết kế. Chương 2- Lớp và đối tượng 6 Phương pháp luận hướng đối tượng  Mô hình hóa và thiết kế theo hướng đối tượng là một lối suy nghĩ mới về vấn đề cần giải quyết dùng các mô hình được tổ chức xung quanh các khái niệm trong thế giới thực.  Trong một hệ thống thông tin hướng đối tượng, mọi thứ, hay hầu như mọi thứ, được quan điểm như các đối tượng. Chương 2- Lớp và đối tượng 7  Mỗi đối tượng là sự kết hợp của cả hai thành phần đặc trưng là cấu trúc dữ liệu (các thuộc tính) và hoạt động (các thủ tục xử lý dữ liệu). Phương pháp luận hướng đối tượng  Phương pháp luận theo quan điểm của J.Rumbaugh bao gồm xây dựng một mô hình của hệ thống trong lãnh vực ứng dụng và thêm chi tiết cài đặt trong quá trình thiết kế hệ thống.  Các ký hiệu đồ họa được sử dụng để biểu diễn các khái niệm hướng đối tượng. Chương 2- Lớp và đối tượng 8  Cách tiếp cận này được gọi là kỹ thuật thiết kế bằng mô hình (OMT: Object Modeling Technique). Phương pháp luận hướng đối tượng  Kỹ thuật mô hình hoá OMT bao gồm các bước: Phân tích Thiết kế hệ thống Thiết kế đối tượng Cài đặt Chương 2- Lớp và đối tượng 9 Các khái niệm hướng đối tượng  Trừu tượng hoá : • Nhấn mạnh vào các khía cạnh cốt yếu vốn có của một thực thể và bỏ qua những tính chất riêng biệt. • Sử dụng trừu tượng hoá trong phân tích có nghĩa là làm việc với các khái niệm trong lãnh vực ứng dụng và bỏ qua chi tiết cài đặt. • Hầu hết các ngôn ngữ lập trình hiện đại đều hổ trợ trừu tượng Chương 2- Lớp và đối tượng 10 hoá. Nhưng sự trừu tượng hóa được tận dụng trong tiếp cận đối tượng với tính kế thừa (inheritance) và tính đa dạng (polymorphism) mang lại hiệu quả cao hơn. Các khái niệm hướng đối tượng  Tính đóng gói : • Tách rời các khía cạnh giao diện với bên ngoài của đối tượng với chi tiết cài đặt bên trong. • Tính đóng gói ngăn chặn khả năng một chương trình trở nên quá phụ thuộc lẫn nhau dẫn tới hậu quả một sự thay đổi nhỏ có thể ảnh hưởng lớn đến toàn bộ hệ thống. • Trong tiếp cận O.O. khả năng kết hợp dữ liệu và hành vi trong Chương 2- Lớp và đối tượng 11 một thực thể duy nhất giúp cho tính đóng gói rõ ràng hơn và hiệu quả hơn. Các khái niệm hướng đối tượng  Kết hợp dữ liệu và hành vi: • Trong cách tiếp cận thủ tục cổ điển, hệ thống được xây dựng trên hai sơ đồ phân cấp chằng chịt: sơ đồ phân cấp dữ liệu và sơ đồ phân cấp thủ tục, trong đó sự liên hệ giữa một loại dữ liệu và các thủ tục xử lý dữ liệu rất mờ nhạt, dẫn đến khó khăn trong việc sửa chữa, nâng cấp trong tương lai. • Cách tiếp cận O.O. loại bỏ những nhược điểm kể trên bằng Chương 2- Lớp và đối tượng 12 cách kết hợp dữ liệu và phần thủ tục xử lý dữ liệu vào trong một thực thể duy nhất, hệ thống trở thành một sơ đồ phân cấp duy nhất các lớp đối tượng. Các khái niệm hướng đối tượng Sơ đồ phân cấp dữ liệu  Kết hợp dữ liệu và hành vi Chương 2- Lớp và đối tượng 13 Sơ đồ phân cấp lớp Sơ đồ phân cấp thủ tục Được thay bằng Đối tượng và lớp  Ta định nghĩa một đối tượng là một "cái gì đó" có ý nghĩa cho vấn đề ta quan tâm. Đố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 trong máy.  Mỗi đối tượng có một nét nhận dạng để phân biệt nó với các đối tượng khác. Nét nhận dạng mang ý nghĩa các đối tượng được phân biệt với nhau do sự tồn tại vốn Chương 2- Lớp và đối tượng 14 có của chúng chứ không phải các tính chất mà chúng có. Đối tượng và lớp  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).  Một thuộc tính (attribute) là một giá trị dữ liệu cho mỗi đối tượng trong lớp. Tên, Tuổi, Cân nặng là các thuộc tính của Người. Chương 2- Lớp và đối tượng 15  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. Sơ đồ đối tượng  Ta dùng sơ đồ đối tượng để mô tả các 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 và phần thứ ba mô tả các thao tác của các đối tượng trong lớp đó. Chương 2- Lớp và đối tượng 16 Sơ đồ lớp và sơ đồ thể hiện Sinh viên Họ tên Năm sinh Mã số Điểm TB (Sinh viên) Nguyễn Văn A 1984 0610234T 9.2 Tên lớp Thuộc tính Chương 2- Lớp và đối tượng 17 Đi học Đi thi Phân loại Thao tác Sơ đồ lớp Sơ đồ thể hiện Đối tượng và lớp  Cùng một thao tác có thể được áp dụng cho nhiều lớp đối tượng khác nhau, một thao tác như vậy được gọi là có tính đa dạng (polymorphism).  Mỗi thao tác trên mỗi 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).  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 đó. Joe Smith, 25 tuổi, nặng Chương 2- Lớp và đối tượng 18 58kg, là một thể hiện của lớp người. Cài đặt lớp trong C++  Lớp trong C++ là cài đặt của kiểu dữ liệu trừu tượng do người sử dụng định nghĩa, cho phép kết hợp dữ liệu, các phép toán, các hàm liên quan để tạo ra một đơn vị chương trình duy nhất. Các lớp này có đầy đủ ưu điểm và tiện lợi như các kiểu dữ liệu nội tại. Lớp tách rời phần giao diện (chỉ liên quan với người sử dụng) và phần cài đặt lớp. Chương 2- Lớp và đối tượng 19  Lớp trong C++ được cài đặt sử dụng từ khoá struct và class. Ví dụ so sánh: Xây dựng kiểu dữ liệu stack. 1. Cách tiếp cận cổ điển: // Stack1.cpp : //Dung cau truc va ham toan cuc #include typedef int bool; typedef int Item; const bool false = 0, true = 1; Chương 2- Lớp và đối tượng 20 struct Stack { Item *st, *top; int size; }; Ví dụ so sánh (tt) void StackInit(Stack *ps, int sz) { ps->st = ps->top = new Item[ps->size=sz]; } void StackCleanUp(Stack *ps) { delete [] ps->st; Chương 2- Lớp và đối tượng 21 } bool StackFull(Stack *ps) { return (ps->top - ps->st >= ps->size); } Ví dụ so sánh (tt) bool StackEmpty(Stack *ps) { return (ps->top st); } bool StackPush(Stack *ps, Item x) { Chương 2- Lớp và đối tượng 22 if (StackFull(ps)) return false; *ps->top++ = x; return true; } Ví dụ so sánh (tt) bool StackPop(Stack *ps, Item *px) { if (StackEmpty(ps)) return false; *px = *--ps->top; return true; } Chương 2- Lớp và đối tượng 23 Ví dụ so sánh (tt) void XuatHe16(long n) { static char hTab[] = “0123456789ABCDEF”; Stack s; StackInit(&s,8); int x; do { StackPush(&s, n%16); Chương 2- Lớp và đối tượng 24 n /= 16; } while(n); while(StackPop(&s,&x)) cout << hTab[x]; StackCleanUp(&s); } Ví dụ so sánh (tt) Nhận xét:  Giải quyết được vấn đề.  Khai báo cấu trúc dữ liệu nằm riêng, các hàm xử lý dữ liệu nằm riêng ở một nơi khác. Do đó khó theo dõi quản lý khi hệ thống lớn. Vì vậy khó bảo trì.  Mọi thao tác đều có tham số đầu tiên là con trỏ đến đối tượng cần thao tác. Tư tưởng thể hiện ở đây là hàm hay Chương 2- Lớp và đối tượng 25 thủ tục đóng vai trò trọng tâm. Đối tượng được gởi đến cho hàm xử lý.  Trình tự sử dụng qua các bước: Khởi động, sử dụng thực sự, dọn dẹp. Ví dụ so sánh (tt) 2. Cách tiếp cận dùng hàm thành phần: //... struct Stack { Item *st, *top; int size; void Init(int sz) {st = top = new Item[size=sz];} Chương 2- Lớp và đối tượng 26 void CleanUp() {if (st) delete [] st;} bool Full() const {return (top - st >= size);} bool Empty() const {return (top <= st);} bool Push(Item x); bool Pop(Item *px); }; Ví dụ so sánh (tt) bool Stack::Push(Item x) { if (Full()) return false; *top++ = x; return true; } Chương 2- Lớp và đối tượng 27 bool Stack::Pop(Item *px) { if (Empty()) return false; *px = *--top; return true; } Ví dụ so sánh (tt) void XuatHe16(long n) { static char hTab[] = “0123456789ABCDEF”; Stack s; s.Init(8); int x; do { Chương 2- Lớp và đối tượng 28 s.Push(n%16); n /= 16; } while(n); while(s.Pop(&x)) cout << hTab[x]; s.CleanUp(); } Ví dụ so sánh (tt) Nhận xét:  Giải quyết được vấn đề.  Dữ liệu và các hàm xử lý dữ liệu được gom vào một chỗ bên trong cấu trúc. Do đó dễ theo dõi quản lý, dễ bảo trì nâng cấp.  Các thao tác đều bớt đi một tham số so với cách tiếp cận cổ điển. Vì vậy việc lập trình gọn hơn. Tư tưởng thể hiện Chương 2- Lớp và đối tượng 29 ở đây là đối tượng đóng vai trò trọng tâm. Đối tượng thực hiện thao tác trên chính nó.  Trình tự sử dụng qua các bước: Khởi động, sử dụng thực sự, dọn dẹp. Các hàm thành phần.  Là hàm được khai báo trong lớp. Hàm thành phần có thể được định nghĩa bên trong hoặc bên ngoài lớp.  Hàm thành phần có nghi thức giao tiếp giống với các hàm bình thường khác: có tên, danh sách tham số, giá trị trả về.  Gọi hàm thành phần bằng phép toán dấu chấm (.) hoặc dấu mũi tên (->). Chương 2- Lớp và đối tượng 30 Stack s, *ps = &s; s.Init(10); for (int i = 0; i < 20; i++) ps->Push(i); Lớp  Trong cách tiếp cận dùng struct và hàm thành phần, người sử dụng có toàn quyên truy xuất, thay đổi các thành phần dữ liệu của đối tượng thuộc cấu trúc. Ví dụ: Stack s; s.Init(10); s.size = 100; // Nguy hiem for (int i = 0; i < 20; i++) Chương 2- Lớp và đối tượng 31 s.Push(i);  Vì vậy, ta không có sự an toàn dữ liệu. Lớp là một phương tiện để khắc phục nhược điểm trên.  Lớp có được bằng cách thay từ khoá struct bằng từ khoá class. Lớp  Trong lớp mọi thành phần mặc nhiên đều là riêng tư (private) nghĩa là thế giới bên ngoài không được phép truy xuất. Do đó có sự an toàn dữ liệu. class Stack { Item *st, *top; int size; Chương 2- Lớp và đối tượng 32 void Init(int sz) {st = top = new Item[size=sz];} void CleanUp() {if (st) delete [] st;} bool Full() const {return (top - st >= size);} bool Empty() const {return (top <= st);} bool Push(Item x); bool Pop(Item *px); }; Lớp  Phát biểu: s.size = 100; // Bao sai Sẽ bị báo sai lúc biên dịch, nhờ đó tránh được những lỗi lúc chạy chương trình (run-time error) rất khó tìm khi thực hiện chương trình. Chương 2- Lớp và đối tượng 33 Thuộc tính truy xuất  Tuy nhiên lớp như trên trở thành vô dụng vì các hàm thành phần cũng trở thành private và không ai dùng được. Điều đó được khắc phục nhờ thuộc tính truy xuất.  Thuộc tính truy xuất của một thành phần của lớp chỉ rõ phần chương trình được phép truy xuất đến nó. • Thuộc tính private • Thuộc tính public Chương 2- Lớp và đối tượng 34 Thuộc tính truy xuất  Các thành phần là nội bộ của lớp, bao gồm dữ liệu và các hàm phục vụ nội bộ được đặt trong phần private. Các hàm nhằm mục đích cho người sử dụng dùng được đặt trong phần public.  Ví dụ sau minh hoạ thuộc tính truy xuất. Chương 2- Lớp và đối tượng 35 // Stack.h class Stack { Item *st, *top; int size; void Init(int sz) {st = top = new Item[size=sz];} void CleanUp() {delete [] st;} public: Stack(int sz = 20) {Init(sz);} Chương 2- Lớp và đối tượng 36 ~Stack() {delete [] st;} bool Full() const {return (top - st >= size);} bool Empty() const {return (top <= st);} bool Push(Item x); bool Pop(Item *px); }; Ví dụ về lớp và thuộc tính truy xuất // Stack.cpp #include "stack.h" bool Stack::Push(Item x) { if (Full()) return false; *top++ = x; return true; } Chương 2- Lớp và đối tượng 37 bool Stack::Pop(Item *px) { if (Empty()) return false; *px = *--top; return true; } Ví dụ về lớp và thuộc tính truy xuất // he16.cpp #include "stack.h" void XuatHe16(long n) { static char hTab[] = “0123456789ABCDEF”; Stack s(8); int x; do { Chương 2- Lớp và đối tượng 38 s.Push(n%16); n /= 16; } while(n); while(s.Pop(&x)) cout << hTab[x]; } Sử dụng phạm vi truy xuất  Phạm vi truy xuất được sử dụng đúng sẽ cho phép ta kết luận: Nhìn vào lớp thấy được mọi thao tác trên lớp.  Người dùng bình thường có thể khai thác hết các chức năng (public) của lớp.  Người dùng cao cấp có thể thay đổi chi tiết cài đặt, cải tiến giải thuật các hàm thành phần. Chương 2- Lớp và đối tượng 39 Tự tham chiếu  Là tham số ngầm định của hàm thành phần trỏ đến đối tượng. Nhờ đó hàm thành phần biết được nó đang thao tác trên đối tượng nào.  Khi một đối tượng gọi một thao tác, địa chỉ của đối tượng được gởi đi một cách ngầm định với tên this, tên các thành phần của đối tượng được hiểu là của đối tượng có địa chỉ this này. Chương 2- Lớp và đối tượng 40 bool Stack::Push(Item x) { if (Full()) // if (this->Full()) return false; *top++ = x; // this->top++ = x; return true; } Phương thức thiết lập và hủy bỏ.  Phương thức thiết lập và huỷ bỏ được xây dựng nhằm mục đích khắc phục lỗi quên khởi động đối tượng hoặc khởi động dư. Việc quên khởi động đối tượng thường gây ra những lỗi rất khó tìm.  Phương thức thiết lập là hàm thành phần đặc biệt được tự động gọi đến mỗi khi một đối tượng thuộc lớp được tạo ra. Người ta thường lợi dụng đặc tính trên để khởi Chương 2- Lớp và đối tượng 41 động đối tượng.  Phương thức thiết lập có tên trùng với tên lớp để phân biệt nó với các hàm thành phần khác. Phương thức thiết lập và hủy bỏ.  Có thể có nhiều phiên bản khác nhau của phương thức thiết lập  Phương thức huỷ bỏ là hàm thành phần đặc biệt được tự động gọi đến mỗi khi một đối tượng bị huỷ đi. Người ta thường lợi dụng đặc tính trên để dọn dẹp đối tượng.  Phương thức huỷ bỏ bắt đầu bằng dấu ngã (~) theo sau bởi tên lớp để phân biệt nó với các hàm thành phần Chương 2- Lớp và đối tượng 42 khác.  Chỉ có thể có tối đa một phương thức hb. Phương thức thiết lập và hủy bỏ. typedef int Item; class Stack { Item *st, *top; int size; void Init(int sz); void CleanUp() {delete [] st;} public: Stack(int sz = 20) {Init(sz);} Chương 2- Lớp và đối tượng 43 ~Stack() {CleanUp();} bool Full() const {return (top - st >= size);} bool Empty() const {return (top <= st);} bool Push(Item x); bool Pop(Item *px); }; Hàm bạn (friends)  Nguyên tắc chung khi thao tác trên lớp là thông qua các hàm thành phần. Tuy nhiên có những trường hợp ngoại lệ, khi hàm phải thao tác trên hai lớp.  Hàm bạn của một lớp là hàm được khai báo ở bên ngoài nhưng được phép truy xuất các thành phần riêng tư của lớp.  Ta làm một hàm trở thành hàm bạn của lớp bằng cách Chương 2- Lớp và đối tượng 44 đưa khai báo của hàm đó vào trong lớp, thêm từ khoá friend ở đầu.  Ta dùng hàm bạn trong trường hợp hàm phải là hàm toàn cục nhưng có liên quan mật thiết với lớp, hoặc là hàm thành phần của một lớp khác. Hàm thành phần hằng  Hàm thành phần hằng là hàm thành phần có thể áp dụng được cho các đối tượng hằng.  Ta qui định một hàm thành phần là hằng bằng cách thêm từ khoá const vào cuối khai báo của nó.  Ta khai báo hàm thành phần là hằng khi nó không thay đổi các thành phần dữ liệu của đối tượng. Chương 2- Lớp và đối tượng 45 Hàm thành phần hằng inline char *strdup(const char *s) { return strcpy(new char[strlen(s) + 1], s); } class string { char *p; Chương 2- Lớp và đối tượng 46 public: string(char *s = "") {p = strdup(s);} ~string() {delete [] p;} string(const string &s2) {p = strdup(s2.p);} void Output() const {cout << p;} void ToLower() {strlwr(p);} }; Hàm thành phần hằng void main() { const string Truong("DH BC TDT"); string s("ABCdef"); s.Output(); s.ToLower(); s.Output(); Chương 2- Lớp và đối tượng 47 Truong.Output(); Truong.ToLower(); // Bao loi } Thành phần tĩnh (static members)  Thành phần dữ liệu tĩnh là thành phần dữ liệu dùng chung cho mọi đối tượng thuộc lớp.  Hàm thành phần tĩnh là hàm thành phần có thể hoạt động không cần dữ liệu của đối tượng, nói cách khác, nó không cần đối tượng.  Ta dùng hàm thàn