Tính Đóng Gói Trong Lập Trình Hướng Đối Tượng
NỘI DUNG BÀI VIẾT
Trong phần này chúng ta sẽ tìm hiểu sâu hơn vào trọng tâm tính chất của OOP, cụ thể là tính đóng gói nhé.
1. Tính đóng gói (Encapsulation)
Hiểu đơn giản, gói dữ liệu và thông tin vào trong một lớp (class) được gọi là tính đóng gói.
Ví dụ về tính đóng gói:
class mayvitinh {
private:
string mausac;
int chieudai, chieurong;
public:
void input()
{
cout << "Nhap mau sac may: ";
fflush(stdin);
getline(cin, this->mausac);
cout << "Nhap chieu dai may: ";
cin >> this->chieudai;
cout << "Nhap chieu rong may: ";
cin >> this->chieurong;
}
void output()
{
cout << "Mau sac may: " << this->mausac << endl;
cout << "Chieu dai may: " << this->chieudai << endl;
cout << "Chieu rong may: " << this->chieurong << endl;
}
};
Trong đoạn code trên tính đóng gói được thể hiện qua các thuộc tính mausac, chieudai, chieurong và phương thức input(), output() vào trong class mayvitinh. Bạn không thể truy cập đến các private
data hoặc gọi đến private
methods của class từ bên ngoài class đó.
Có thể nói tính đóng gói (Encapsulation) là cơ chế của che giấu dữ liệu (Data Hiding) bởi chúng được lớp (class) che giấu đi (ở dạng private
) một số dữ liệu, hàm và phương thức để đảm bảo rằng các dữ liệu đó sẽ được truy cập và sử dụng đúng mục đích, đúng cách thông qua các hàm và phương thức ở dạng public
mà class cung cấp. Đó là lý do bạn không thể truy cập đến các thuộc tính private
hoặc gọi đến phương thức private
của class từ bên ngoài class đó.
Tính đóng gói được thể hiện khi mỗi đối tượng mang trạng thái là private
ở bên trong một class
và những đối tượng khác không thể truy cập trực tiếp vào phạm vi này. Thay vào đó họ chỉ có thể gọi các hàm mang phạm vi public
được gọi là phương thức.
Cụ thể, đối tượng sẽ mang trạng thái riêng thông qua các phương thức và không một class nào khác có thể truy cập vào được trừ khi cho phép. Nói chung trạng thái đối tượng không hợp lệ thường do chưa được kiểm tra tính hợp lệ, các bước thực hiện không đúng trình tự hoặc bị bỏ qua nên trong OOP có một quy tắc quan trọng cần nhớ đó là phải luôn khai báo các trạng thái bên trong của đối tượng là private
và chỉ cho truy cập qua các public/protected
method
Hãy tưởng tượng chúng ta xây dựng trò chơi tên Lửa Không Miễn Phí và có các nhân vật giao tiếp với nhau. Chúng ta muốn áp dụng tính đóng gói nên đã gói gọn tất cả những gì liên quan tới các nhân vật với nhau thành một lớp nhân vật, nó trông như thế này:
Chúng ta có thể ăn Blue nhung không thể điều chỉnh lượng năng lượng của nhân vật
Ở đây trạng thái của nhân vật là các thuộc tính private
năng lượng, máu, thông thạo và phương thức private tung chiêu mà có thể được gọi bất cứ khi nào nhưng lớp khác thì không thể. Thay vào đó ở lớp khác có thể truy cập những phương thức public
như ăn blue, Ctrl+6 và hạ gục kẻ địch. Đó chính là tính đóng gói (Encapsulation).
Vậy bạn có nghĩ có cách nào chúng ta có thể truy cập các phần tử private
của một class
từ các hàm ngoài class
đó hay từ các class
khác không ?
Có đấy, chúng ta sẽ nhờ tới từ khóa friend
, cụ thể là hàm bạn và lớp bạn.
2. Hàm bạn
Nếu một hàm ngoài lớp được định nghĩa là một hàm bạn (Friend function), thì dữ liệu protected
và riêng tư private
của một lớp có thể được truy cập bằng cách sử dụng hàm. Một lớp có thể có nhiều hàm bạn, và chúng phải nằm bên ngoài class
Cú pháp:
class TenLop
{
friend KieuDuLieu TenHam([Tham so]);
};
Ví dụ:
#include <iostream>
using namespace std;
class MayLaptop;
class MayviTinh {
int chieudaiMVT;
public:
void setChieudaiMVT(int chieudaiMVT) {
this->chieudaiMVT = chieudaiMVT;
}
void HienThi() {
cout << "Chieu dai may vi tinh la " << this->chieudaiMVT << endl;
}
friend void TimChieuDaiNhoNhat(MayviTinh, MayLaptop); // Khai báo hàm bạn
};
class MayLaptop {
int chieudaiML;
public:
void setChieudaiML(int chieudaiML) {
this->chieudaiML = chieudaiML;
}
void HienThi() {
cout << "Chieu dai may laptop la " << this->chieudaiML << endl;
}
friend void TimChieuDaiNhoNhat(MayviTinh, MayLaptop); // Khai báo hàm bạn
};
void TimChieuDaiNhoNhat(MayviTinh mayLenovo, MayLaptop mayAsus) {
cout << "Chieu dai nho nhat trong 2 may la: ";
if(mayLenovo.chieudaiMVT <= mayAsus.chieudaiML)
cout << mayLenovo.chieudaiMVT << endl;
else
cout << mayAsus.chieudaiML << endl;
}
int main() {
MayviTinh mayLenovo;
MayLaptop mayAsus;
mayLenovo.setChieudaiMVT(18);
mayAsus.setChieudaiML(9);
mayLenovo.HienThi();
mayAsus.HienThi();
TimChieuDaiNhoNhat(mayLenovo, mayAsus);
return 0;
}
Sau khi thực hiện chương trình sẽ cho kết quả:
3. Lớp bạn
Tương tự như hàm bạn, lớp bạn ( friend class ) cũng cho phép lớp bạn của lớp kia truy cập các thành viên private
.
Khai báo lớp A là bạn của lớp B không có nghĩa lớp B là bạn của lớp A (chỉ có tính 1 chiều). Điều đó có nghĩa là chỉ có lớp A truy cập được thành viên của lớp B, nhưng ngược lại lớp B không thể truy cập ngược lại của lớp A.
Chúng ta cùng xem ví dụ đơn giản về lớp bạn trong C++:
#include <iostream>
using namespace std;
class mayLaptop {
int chieudai = 10;
friend class mayVitinh;
};
class mayVitinh {
public:
void HienThi(mayLaptop mayAcer) {
cout << "Chieu dai cua may laptop la: "<< mayAcer.chieudai;
}
};
int main() {
mayLaptop mayAcer;
mayVitinh mayLenovo;
mayLenovo.HienThi(mayAcer);
return 0;
}
Và kết quả sau khi thực thi chương trình trên như sau:
Trong ví dụ trên, mayVitinh được khai báo là friend
trong lớp mayLaptop
. Do đó, mayVitinh
là bạn của mayLaptop
. mayVitinh
có thể truy cập các thành viên private của mayLaptop
.
Tạm kết
Vậy là chúng ta đã hiểu hơn về một tính chất đặc trưng của lập trình hướng đối tượng, cụ thể là tính đóng gói và những kiến thức về hàm bạn, lớp bạn. Bài viết của mình xin kết thúc tại đây, mình hy vọng bài này sẽ giúp các bạn nhiều hơn trong quá trình tìm hiểu OOP.
Trả lời