Tính Đóng Gói Trong Lập Trình Hướng Đối Tượng

Tính Đóng Gói Trong Lập Trình Hướng Đối Tượng

Qua những phần trước chúng ta đã nắm được những kiến thức cơ bản của lập trình hướng đối tượng cũng như các cú pháp khai báo. 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+6hạ 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. 

Các bạn có thể rate và comment góp ý ở bên dưới nếu thấy bất cứ điều gì không chính xác để những bài sau tốt hơn. Cảm ơn các bạn đã theo dõi.