Lớp là khuơn mẫu để tạo các đối tƣợng (tạo các thể hiện). Mỗi đối tƣợng cĩ cấu trúc và hành vi giống nhƣ lớp đối tƣợng mà nĩ đƣợc tạo từ đĩ.
Lớp là cái ta thiết kế và lập trình
Đối tƣợng là cái ta tạo (từ một lớp) tại thời gian chạy. Ví dụ lớp Human giúp chúng ta tạo ra nhiều đối tƣợng nhƣ Thomas, Peter, ...
1.2.2. Lớp - Kiểu dữ liệu trừu tượng
Khi khai báo lớp xong thì lớp đƣợc xem nhƣ là một kiểu dữ liệu, nhƣng kiểu dữ liệu này là kiểu dữ liệu trừu tƣợng bởi vì khi mơ tả lớp chúng ta đã trải qua bƣớc trừu tƣợng hĩa dữ liệu tức là chỉ tập chung vào những chi tiết chính, cần thiết và bỏ qua những chi tiết khơng cần thiết. Đã là kiểu dữ liệu thì chắc chắn sẽ cho phép khai báo biến, và biến này chính là đối tƣợng của lớp đĩ, chúng ta cĩ thể tạo ra nhiều biến của kiểu dữ liệu này tức là chúng ta cĩ thể tạo ra vơ số các đối tƣợng của một lớp.
Tài liệu giảng dạy Lập Trình Hƣớng Đối Tƣợng 31
So sánh v i ập tr nh cĩ cấu trúc
Lập trình hƣớng đối tƣợng Lập trình hƣớng thủ tục
Lớp đối tƣợng Kiểu dữ liệu cĩ cấu trúc (structure, record)
Đối tƣợng Biến cĩ cấu trúc
Phƣơng thức Phép tốn hay hàm tác động lên kiểu dữ liệu
Truyền thơng điệp đến đối tƣợng hay gọi một phƣơng thức tác động lên một đối tƣợng
Gọi hàm hay thực hiện phép tốn
Mỗi đối tƣợng sẽ thực hiện những cơng việc cần thiết khi nhận đƣợc thơng điệp thích hợp mà nĩ hiểu và chấp nhận. Trong đa số các ngơn ngữ lập trình hƣớng đối tƣợng hiện nay, việc truyền thơng điệp đến đối tƣợng của lớp đƣợc thực hiện bằng cách gọi phƣơng thức của lớp cho đối tƣợng đĩ.
Về mặt bản chất, lập trình hƣớng đối tƣợng là sự phát triển và hồn thiện của lập trình cấu trúc. Tuy nhiên cơng nghệ lập trình hƣớng đối tƣợng đƣợc đề xuất nhằm để khắc phục các điểm hạn chế của lập trình cổ điển. Trong giáo trình này, chúng ta sẽ khảo sát kỹ để hiểu rõ về những nét đặc sắc của lập trình hƣớng đối tƣợng.
1.3. Vì sao là hƣớng đối tƣợng?
Giả sử ta cĩ đối tƣợng ngƣời tên là Long, đối tƣợng này cĩ hành vi là Đihoc(). Khi muốn diễn đạt ý “Long đi học”. Nếu diễn đạt theo hƣớng thủ tục thì gọi hàm
Đihoc(Long), cịn nếu diễn đạt theo hƣớng đối tƣợng thì lấy đối tƣợng Long làm
trung tâm, đối tƣợng này yêu cầu hành động cho nên chúng ta cĩ Long Đihoc() Rõ
ràng là cách diễn đạt theo hƣớng đối tƣợng sẽ tự nhiên hơn cách diễn đạt theo hƣớng thủ tục.
Tịm lại:
Diễn đạt theo hƣớng thủ tục: Tên hành vi (Đối tƣợng dữ liệu); Diễn đạt theo hƣớng đối tƣợng: Đối tƣợng dữ liệu. Tên hành vi ();
2. THIẾT KẾ VÀ CÀI ĐẶT LỚP
Khi viết chƣơng trình theo phƣơng pháp hƣớng đối tƣợng ta phải trả lời các câu hỏi:
Chƣơng trình liên quan tới những lớp đối tƣợng nào? Mỗi đối tƣợng cần cĩ những dữ liệu và thao tác nào?
Tài liệu giảng dạy Lập Trình Hƣớng Đối Tƣợng 32 Các đối tƣợng quan hệ với nhau nhƣ thế nào trong chƣơng trình?
Từ đĩ ta thiết kế các lớp đối tƣợng và tổ chức trao đổi thơng tin giữa các đối tƣợng, ra lệnh để đối tƣợng thực hiện các nhiệm vụ thích hợp.
2.1. Khai báo và cài đặt lớp
Cú pháp: TÊN LỚP Dữ liệu thành viên Hàm thành viên 2.1.1. Cài đặt dữ liệu thành phần.
Khi xác định đƣợc thuộc tính hay dữ liệu của lớp, chúng ta tiến hành khai báo trong lớp. Việc khai báo giống nhƣ khai báo biến, mỗi thuộc tính là khai báo một biến. Tất cả các khai báo này đƣợc đặt sau <quyền truy xuất>, và cụ thể quyền truy xuất là gì chúng ta sẽ tìm hiểu ngay bên dƣới ở mục 2.1.3. Nếu chỉ dừng ở việc khai báo thuộc tính nhƣ thế này thì khai báo lớp giống nhƣ khai báo struct.
Ví dụ: định nghĩa lớp Sinh viên.
Class TENLOP {
<Quyền truy xuất>:
Datatype1 memberdata1; Datatype2 memberdata2; ……………
<Quyền truy xuất>:
memberFunction1(); memberFunction2(); ………….
Tài liệu giảng dạy Lập Trình Hƣớng Đối Tƣợng 33 2.1.2. Cài đặt hàm thành phần (phương thức của lớp).
Cài đặt phƣơng thức của lớp giống nhƣ việc cài đặt các hàm mà chúng ta đã học, chỉ khác một điều rằng nếu là phƣơng thức thì nội dung của phƣơng thức này phải thao tác trên dữ liệu của lớp (tức thuộc tính của lớp), cịn khái niệm hàm chính là những hàm chức năng ở bên ngồi lớp, khơng phải là hàm thành viên của lớp, các hàm này cĩ thể đƣợc sử dụng ở bất cứ nơi đâu (miễn là phải khai báo trƣớc khi sử dụng) ngay cả trong một lớp.
Tất cả các phƣơng thức của lớp đƣợc đặt sau <quyền truy xuất>, cụ thể sẽ đƣợc trình bày trong mục 2.1.3.
Ví dụ: Xét lại ví dụ với lớp SinhVien
Để định nghĩa phƣơng thức chúng ta cĩ hai cách:
Cách 1: Định nghĩa phƣơng thức ngay trong lớp.
Ví dụ:
class SinhVien {
<quyền truy xuất>: char masv[10]; char hoten[20]; float dtb;
<quyền truy xuất>: void XepLoai(); ...
};
class SinhVien {
<quyền truy xuất>: char masv[10]; char hoten[20]; float dtb; }; class SinhVien {
<quyền truy xuất>: char masv[10]; char hoten[20]; float dtb; };
Tài liệu giảng dạy Lập Trình Hƣớng Đối Tƣợng 34
Cách 2: Khai báo phƣơng thức trong lớp, sau đĩ định nghĩa ở ngồi lớp.
Khai báo trong lớp:
Định nghĩa ngồi lớp: Trong chƣơng trình, ở ngồi phạm vi của lớp chúng ta
cĩ thể định nghĩa phƣơng thức theo cú pháp sau:
<Kiểu Trả Về> TênLớp:: <TênPhƣơngThức>(Danh sách tham số)
class SinhVien {
<quyền truy xuất>: char masv[10]; char hoten[20]; float dtb;
<quyền truy xuất>: void XepLoai(); ...
};
class SinhVien {
<quyền truy xuất>: char masv[10]; char hoten[20]; float dtb;
<quyền truy xuất>: void XepLoai() {
if(dtb>=8) cout«”XL giỏi”; else if (dtb >=7) cout«”XL khá”;
else cout«”XL trung bình”; }
Tài liệu giảng dạy Lập Trình Hƣớng Đối Tƣợng 35
{
//nội dung của phƣơng thức }
Cú pháp trên cĩ xuất hiện tốn tử phạm vi „::‟, tốn tử này đi cùng với tên lớp để nĩi lên rằng phƣơng thức mà chúng ta đang định nghĩa thuộc lớp nào. Bởi vì trong chƣơng trình cĩ thể cĩ rất nhiều lớp khác nhau và cĩ thể các lớp này lại cĩ các phƣơng thức trùng tên nên khi định nghĩa bên ngồi lớp thì phải chỉ định rõ ràng là phƣơng thức này là của lớp nào.
Ví dụ:
void SinhVien::XepLoai() {
if(dtb>=8) cout«”XL giỏi”; else if (dtb >=7) cout«”XL khá”; else cout«”XL trung bình”;
}
2.1.3. Thuộc tính truy xuất
Thuộc tính truy xuất bao gồm: private, public, protected. Mỗi thuộc tính truy
xuất này thể hiện các quyền truy xuất khác nhau, cho phép các đối tƣợng bên ngồi lớp truy xuất hay khơng truy xuất đến các thành phần của lớp.
Thuộc tính truy xuất private:
Thành phần của lớp đặt sau từ khĩa này thì cĩ nghĩa là những thành phần này là “riêng tƣ”, chỉ đƣợc phép truy cập trong lớp và cấm truy cập ở bất kỳ nơi nào ở ngồi lớp. Nĩi cách khác chỉ cĩ các phƣơng thức của lớp mới đƣợc phép truy cập hay truy xuất tới các thành phần đã khai báo là private. Thơng thƣờng để thể hiện đúng đặc điểm của lập trình hƣớng đối tƣợng thì các thuộc tính của lớp phải đƣợc khai báo là private.
Thuộc tính truy xuất public:
Public cĩ nghĩa là “cơng cộng”, tức là các thành phần của lớp mà đƣợc khai báo sau từ khĩa public này đều đƣợc sử dụng ở bên ngồi lớp, ở bất cứ nơi nào cũng cĩ thể truy xuất đƣợc tới những thành phần này. Thơng thƣờng thì các phƣơng thức của lớp đƣợc khai báo là public.
Tài liệu giảng dạy Lập Trình Hƣớng Đối Tƣợng 36 Qua ví dụ này chúng ta thấy thuộc tính masv, hoten, dtb đƣợc khai báo là
private nên chỉ cĩ các thành phần ở trong lớp mới truy xuất đƣợc, cụ thể là phƣơng thức XepLoai(). Các phạm vi khác khơng thể truy xuất nhƣ trong hàm main() đã tạo ra một đối tƣợng của lớp SinhVien hay một biến của kiểu dữ liệu SinhVien, sau đĩ truy xuất tới thuộc tính dtb của x để nhập dữ liệu. Câu lệnh này sẽ báo lỗi khi biên dịch bởi vì tại hàm main() (ở ngồi lớp) khơng đƣợc phép truy xuất.
Đối với phƣơng thức XepLoai() đƣợc khai báo là public, nên ở bất kỳ nơi nào cũng cĩ thể sử dụng, truy xuất tới nĩ và cụ thể là tại hàm main() cĩ thể yêu cầu đối tƣợng x gọi hành động XepLoai() mà khơng bị lỗi.
Thuộc tính truy xuất protected:
class SinhVien { private: char masv[10]; char hoten[20]; float dtb; public: void XepLoai() {
if(dtb>=8) cout«”XL giỏi”; else if (dtb >=7) cout«”XL khá”;
else cout«”XL trung bình”; }
};
void main() {
SinhVien x;
cin»x.dtb; // lỗi truy xuất
x.XepLoai(); // đƣợc phép truy xuất }
Tài liệu giảng dạy Lập Trình Hƣớng Đối Tƣợng 37 Những thành phần đƣợc đặt sau protected thì cũng giống nhƣ private là chỉ cho phép những thành phần của lớp truy xuất, ngồi ra thành phần đƣợc khai báo là
protected cịn cho phép những thành phần của lớp dẫn xuất của lớp này đƣợc sử
dụng, đƣợc truy xuất. Thuộc tính này chỉ cĩ ý nghĩa khi trong chƣơng trình cĩ quan hệ kế thừa.
2.1.4. Vấn đề che dấu thơng tin
Sau khi tìm hiểu về các thuộc tính truy xuất chúng ta thấy rằng vấn đề che dấu thơng tin hay tính đĩng gĩi dữ liệu (một trong ba đặc điểm quan trọng của lập trình hƣớng đối tƣợng) đƣợc thể hiện nhờ thuộc tính truy xuất private. Thơng tin (dữ liệu) đƣợc che dấu bên trong lớp, bên ngồi khơng thể nào nhìn thấy hay truy xuất đƣợc. Bên ngồi chỉ sử dụng đƣợc các hành động (phƣơng thức khai báo public) mà khơng thể thấy đƣợc chi tiết cài đặt của các hành động này hay nĩi cách khác dữ liệu đã đƣợc đĩng. Chúng ta cĩ thể tƣởng tƣợng lớp nhƣ là một cái hộp đen vậy.
2.2. Giao diện và chi tiết cài đặt
Để cài đặt chúng ta sử dụng mơi trƣờng Visual studio C++ 6.0, 2005, 2008, 2010
Sau đây là minh họa giao diện cài đặt Visual studio C++ 2010
Hình 2-2. Mở Microsoft visual C++
Sau đĩ xuất hiện cửa sổ:
Tài liệu giảng dạy Lập Trình Hƣớng Đối Tƣợng 38
Hình 2-3. Tạo mới một project
Hình 2-4. Cửa sổ đặt tên project
Thực hiện 4 bƣớc nhƣ hình trên bấm OK.
Sau đĩ xuất hiện một cửa sổ, rồi bấm next để tiếp tục. 1:Chọn 2: Chọn Win32 Console Application 4: Đặt tên project 3:Chọn vị trí lƣu project
Tài liệu giảng dạy Lập Trình Hƣớng Đối Tƣợng 39 Cửa sổ kế tiếp: chọn Empty project rồi bấm finish
Tài liệu giảng dạy Lập Trình Hƣớng Đối Tƣợng 40
Hình 2-5. Cửa sổ chọn Empty project
Tiếp theo chúng ta sẽ cĩ hai sự lựa chọn để viết code:
Lựa chọn 1: Tất cả chƣơng trình chỉ chứa trong một file cĩ phần mở rộng là
cpp.
Tài liệu giảng dạy Lập Trình Hƣớng Đối Tƣợng 41 kế tiếp làm theo hƣớng dẫn hình sau rồi nhấn nút Add.
Hình 2-6.Thêm file source vào project
Kết quả tạo ra cửa sổ giao diện là nơi chúng ta cĩ thể viết code thực thi: 1: chọn
2: Đặt tên file source
Tài liệu giảng dạy Lập Trình Hƣớng Đối Tƣợng 42
Hình 2-7. Giao diện soạn thảo
Lựa chọn 2: là cách cài đặt dƣới dạng thƣ viện
Tài liệu giảng dạy Lập Trình Hƣớng Đối Tƣợng 43 Cửa sổ mới hiện ra:
Sau đĩ bấm Add.
Tài liệu giảng dạy Lập Trình Hƣớng Đối Tƣợng 44
Hình 2-8. Cửa sổ tạo tên lớp
Bấm finish sẽ xuất hiện cửa sổ:
Chọn thẻ Class View:
Chọn Class View
Tài liệu giảng dạy Lập Trình Hƣớng Đối Tƣợng 45 Click phải vào tên lớp để tiến hành khai báo thuộc tính và phƣơng thức
Hình 2-9. Thêm thuộc tính vào lớp
Kiểu dữ liệu Tên thuộc tính Chọn thuộc tính truy xuất
Tài liệu giảng dạy Lập Trình Hƣớng Đối Tƣợng 46 Nhấn finish để kết thúc việc thêm một thuộc tính của lớp. Các thuộc tính khác làm tƣơng tự.
Hình 2-10. Cửa sổ khai báo thuộc tính
Khai báo phƣơng thức:
Hình 2-11. Thêm phƣơng thức vào lớp
Hình 2-12. Khai báo phƣơng thức
Tên phƣơng thức Kiểu trả về của hàm Chọn thuộc tính truy xuất Kiểu tham số của hàm Tên tham số
Tài liệu giảng dạy Lập Trình Hƣớng Đối Tƣợng 47 Nhấn ok rồi lặp lại cho nhiều phƣơng thức khác của lớp
Sau khi tạo xong tất cả thuộc tính và phƣơng thức của lớp chúng ta sẽ cĩ hai file phát sinh. Một file “.cpp” là nơi định nghĩa các phƣơng thức của lớp, cịn một file “.h” là nơi khai báo lớp.
Tài liệu giảng dạy Lập Trình Hƣớng Đối Tƣợng 48
Hình 2-14. Minh họa file .cpp
Cuối cùng chỉ cần thêm vào project một file .cpp, file này chứa hàm main() và là nơi gọi thực thi của các đối tƣợng. Muốn sử dụng lớp đối tƣợng nào thì đầu chƣơng trình chúng ta phải include<file.h> của lớp đĩ.
Nhƣ vậy là đã hồn tất việc tạo giao diện cài đặt. Nhấn Ctrl+F7 để biên dịch
và Ctrl+F5 để chạy chƣơng trình. 2.3. Sử dụng đối tƣợng
Để sử dụng đối tƣợng thì đầu tiên chúng ta tạo ra đối tƣợng bằng câu lệnh khai báo biến, sau đĩ cĩ thể cho đối tƣợng đĩ hoạt động tức gọi các hành động của đối tƣợng đĩ. Hãy nhớ lại rằng ch ng tr nh trong lập trình hƣớng đối tƣợng chính là
sự hoạt động của các đối tƣợng.
Ví dụ
Khai báo nhƣ SinhVien x ; khi đĩ để gọi các phƣơng thức của x chúng ta sử dụng tốn tử chấm “.”, chẳng hạn nhƣ x.XepLoai().
Tài liệu giảng dạy Lập Trình Hƣớng Đối Tƣợng 49 Đối tƣợng đƣợc sinh ra khi cĩ câu lệnh khai báo biến
Đối tƣợng đƣợc giải thốt khi kết thúc chƣơng trình hoặc khi cĩ lệnh hủy đối tƣợng
2.3.2. Thiết lập và hủy đối tượng.
Phƣơng thức thiết lập (cịn gọi là phƣơng thức khởi tạo).
Khi vừa mới đƣợc tạo ra, bản thân đối tƣợng chƣa cĩ dữ liệu ban đầu. Chúng ta khơng thể kiểm sốt đƣợc các ơ nhớ dành cho các thuộc tính của đối tƣợng đang chứa cái gì? Cĩ thể chỉ là một giá trị rác, một giá trị ngẫu nhiên nào đĩ. Vì vậy rất cần thiết để khởi tạo giá trị ban đầu cho đối tƣợng.
Để khởi tạo giá trị ban đầu cho đối tƣợng chúng ta sử dụng phƣơng thức khởi tạo.
Đặc điểm:
- Cĩ tên trùng với tên lớp - Khơng kiểu trả về
- Cĩ thể cĩ nhiều phƣơng thức khởi tạo (các phƣơng thức này đƣợc phân biệt nhờ danh sách tham số truyền vào)
- Khơng cần cĩ câu lệnh gọi mà đƣợc tự động thực thi khi đối tƣợng vừa đƣợc tạo ra.
Ví dụ: hai phƣơng thức nhƣ hình sau đƣợc gọi là các phƣơng thức khởi tạo của
lớp PhanSo.
Phân loại: Cĩ 3 loại phƣơng thức khởi tạo đĩ là phƣơng thức khởi tạo mặc
định, phƣơng thức khởi tạo cĩ tham số và phƣơng thức khởi tạo sao chép.
Tài liệu giảng dạy Lập Trình Hƣớng Đối Tƣợng 50 Là phƣơng thức khởi tạo khơng nhận tham số đầu vào, nội dung của phƣơng thức là gán giá trị mặc định cho các thuộc tính của lớp đối tƣợng.
Cú pháp:
TênLớp() {
//cĩ thể gán giá trị hằng cho thành phần dữ liệu của lớp ở đây } Ví dụ nhƣ: PhanSo() { ts=0; ms=0; }
Phƣơng thức khởi tạo sẽ đƣợc gọi khi cĩ câu lệnh khai báo: PhanSo a;
Nhƣ vậy sau câu lệnh này thì đối tƣợng a sẽ đƣợc khởi gán giá trị ban đầu là phân số cĩ tử là 0 và mẫu là 1.
Phƣơng thức khởi tạo cĩ tham số
Là phƣơng thức khởi tạo nhận tham số đầu vào từ bên ngồi, nội dung của phƣơng thức là lấy giá trị truyền vào để gán cho các thuộc tính của đối tƣợng.
Cú pháp:
TênLớp(danh sách tham số) {
// gán giá trị cho thành phần dữ liệu của lớp ở đây } Ví dụ nhƣ: PhanSo(int t, int m){ ts=t; ms=t; }
Tài liệu giảng dạy Lập Trình Hƣớng Đối Tƣợng 51 Phƣơng thức khởi tạo này sẽ đƣợc gọi khi cĩ câu lệnh khai báo ví dụ nhƣ: PhanSo a(2,3);
Sau khi khai báo đối tƣợng a nhƣ trên thì đối tƣợng a vừa đƣợc cấp phát vùng