Tính Kế Thừa Trong Lập Trình Hướng Đối Tượng

Tính Kế Thừa Trong Lập Trình Hướng Đối Tượng

Trong bài trước, chúng ta hiểu được thế nào là tính đóng gói trong OOP. Ở bài này chúng ta sẽ tìm hiểu thêm một tính chất nữa của lập trình hướng đối tượng đó là tính kế thừa nhé.

Tính kế thừa là gì?

Thử nghĩ chúng ta có các lớp Class mayAsus, Class mayAcer, Class mayLenovo đều có các thuộc tính (attribute): chieudai, chieurong và phương thức (method):  upRam()Khi đó, nếu chúng ta tạo các lớp này thì chúng ta phải viết trong mỗi lớp đều có 3 phương thức trên. Hơn thế nữa, nếu bạn muốn sửa lại code trong một phương thức nào đó thì bạn phải sửa chúng cả ở 3 lớp sẽ rất tốn thời gian, và có thể dễ sai sót. Vì thế tính kế thừa sẽ được sử dụng trong trường hợp này để giải quyết vấn đề trên. 

Tính kế thừa cho phép xây dựng một lớp mới dựa trên các định nghĩa của lớp đã có. Có nghĩa là lớp cha có thể chia sẽ dữ liệu và phương thức cho các lớp con. Các lớp con khỏi phải định nghĩa lại, ngoài ra có thể mở rộng các thành phần kế thừa và bổ sung thêm các thành phần mới. Tái sử dụng mã nguồn 1 cách tối ưu, tận dụng được mã nguồn.

Áp dụng tính kế thừa vào ba lớp trên ta sẽ tạo ra một lớp Class Mayvitinh có các thuộc tính và phương thức: chieudai, chieurongupRam() và các lớp Class mayAcer, Class mayAsus, Class mayLenovo sẽ kế thừa từ Class Mayvitinh

Hình ảnh trên cho thấy khi áp dụng tính kế thừa, ta chỉ cần viết một lần các phương thức kia trong lớp cha và cho các lớp con kế thừa lại. Điều này sẽ tránh việc sai sót khi sửa và tăng khả năng sử dụng lại. Ví dụ, nếu bạn muốn thêm một lớp Class mayMac , bạn chỉ cần khai báo nó kế thừa từ Class Mayvitinh là cũng có thể dùng được các thuộc tính và phương thức trên rồi.

Cú pháp khai báo tính kế thừa:

class lopcon : phamvitruycap
{
   // nội dung lớp con
};

Chúng ta cùng xem ví dụ dưới đây:

#include <bits/stdc++.h>
using namespace std;
 
//Lớp Cha
class Mayvitinh {
public:
    int chieudai;
};
 
// Lớp con kế thừa từ lớp cha
class mayAcer : public Mayvitinh {
public:
    int length;
};
 
int main() {
    mayAcer may1;
    may1.chieudai = 6;
    may1.length = 23;
    cout << "Chieu dai: " << may1.chieudai << endl;
    cout << "Length: " << may1.length << endl;
 
    return 0;
}

Sau khi chạy chương trình sẽ có kết quả:

Trong chương trình trên, class mayAcer là lớp con, nó sẽ được kế thừa các thành viên dữ liệu dạng public từ class MayvitinhNếu để các thành viên dữ liệu trên dạng private thì sẽ không thể dùng kế thừa.

Chúng ta cùng xem bảng sau:

  • public: Nếu kế thừa ở dạng này, sau khi kế thừa, tất cả các thành viên dạng public lớp cha sẽ public ở lớp con, dạng protected ở lớp cha vẫn sẽ là protected ở lớp con.
  • protected: Nếu dùng protected thì sau khi kế thừa, tất cả các thành viên dạng public lớp cha sẽ trở thành protected tại lớp con.
  • private: Trường hợp ta sử dụng private, thì sau khi kế thừa, tất cả các thành viên dạng public  protected ở lớp cha sẽ thành private tại lớp con.

Các loại kế thừa

1. Đơn kế thừa(Single Inheritance):

Đơn kế thừa: nghĩa là một lớp chỉ được kế thừa từ đúng một lớp khác. Hay nói cách khác, lớp con chỉ có duy nhất một lớp cha.

Cú pháp khai báo đơn kế thừa:

class lopcon : phamvidulieu lopcha
{
  // nội dung lớp con
};

Dưới đây là một ví dụ:

#include <iostream>
using namespace std;
 
// Lớp cha
class Mayvitinh
{
public:
    Mayvitinh()
    {
        cout << "This is a computer" << endl;
    }
};
 
// Lớp con kế thừa từ lớp cha
class mayAcer : public Mayvitinh
{
};
 
// main function
int main()
{
    mayAcer may1;
    return 0;
}

Chương trình sẽ cho kết quả:

2. Đa kế thừa (Multiple Inheritance):

Đa kế thừa là một tính năng của ngôn ngữ C++. Trong đó một lớp có thể kế thừa từ nhiều hơn một lớp khác. Nghĩa là một lớp con được kế thừa từ nhiều hơn một lớp cơ sở.

Cú pháp khai báo đa kế thừa:

class lopcon : phamvitruycap lopcha1, phamvitruycap lopcha2, ....
{
  // nội dung của lớp con
};

Ở đây, các lớp cơ sở sẽ được phân tách bằng dấu phẩy , và phạm vi truy cập cho mọi lớp cơ sở phải được chỉ định.

Chúng ta cùng xem ví dụ sau:

#include <iostream>
using namespace std;
 
// Lớp cơ sở thứ nhất
class Mayvitinh
{
public:
    Mayvitinh()
    {
        cout << "This is a computer's brand" << endl;
    }
};

// Lớp cơ sở thứ hai
class Maylaptop
{
public:
    Maylaptop()
    {
        cout << "This is a laptop's brand" << endl;
    }
};
 
// Lớp con kế thừa từ 2 lớp cha
class mayAcer : public Mayvitinh, public Maylaptop
{
};
 
// main function
int main()
{
    mayAcer may1;
    return 0;
}

Sau khi chạy ta sẽ có kết quả sau:

3. Kế thừa đa cấp (Multilevel Inheritance):

Kế thừa đa cấp: Trong kiểu thừa kế này, một lớp dẫn xuất được tạo từ một lớp dẫn xuất khác.

Ví dụ về kế thừa đa cấp:

#include <iostream>
using namespace std;
 
// Lớp cha
class Mayvitinh
{
public:
    Mayvitinh()
    {
        cout << "This is a computer's brand" << endl;
    }
};

// Lớp con kế thừa từ lớp cha
class Maylaptop : public Mayvitinh
{
public:
    Maylaptop()
    {
        cout << "This is a laptop's brand" << endl;
    }
};
 
// Lớp con kế thừa từ lớp cha thứ 2
class mayAcer : public Maylaptop
{
public:
     mayAcer(){
         cout << "This brand is Acer" << endl;
     }
};
 
// main function
int main()
{
    mayAcer may1;
    return 0;
}

Sau khi chạy ta có kết quả:

 

4. Kế thừa phân cấp (Hierarchical Inheritance):

Kế thừa phân cấp: Trong kiểu thừa kế này, sẽ có nhiều hơn một lớp con được kế thừa từ một lớp cha duy nhất.

Chúng ta có ví dụ:

#include <iostream>
using namespace std;
 
// Lớp cha
class Mayvitinh
{
public:
    Mayvitinh()
    {
        cout << "This is a computer's brand" << endl;
    }
};

// Lớp con thứ nhất
class mayAsus : public Mayvitinh
{
};
 
// Lớp con thứ hai
class mayAcer : public Mayvitinh
{
};
 
// main function
int main()
{
    mayAcer may1;
    mayAsus may2;
    return 0;
}

Sau khi chạy ta có kết quả:

5. Kế thừa lai (Kế thừa ảo) – Hybrid (Virtual) Inheritance:

Kế thừa lai (Kế thừa ảo): được thực hiện bằng cách kết hợp nhiều hơn một loại thừa kế.

Chúng ta lấy ví dụ về sự kết hợp của phân cấp và đa kế thừa sau đây:

#include <iostream>
using namespace std;
 
// Lớp cha
class Mayvitinh
{
public:
    Mayvitinh()
    {
        cout << "This is a computer's brand" << endl;
    }
};

// Lớp cha
class Maylaptop
{
public:
    Maylaptop()
    {
        cout << "This is a laptop's brand" << endl;
    }
};
 
// Lớp con thứ nhất
class mayAcer : public Mayvitinh
{
};

// Lớp con thứ hai
class mayAsus : public Mayvitinh, public Maylaptop
{
};
 
// main function
int main()
{
    mayAsus may1; 
    mayAcer may2;
    return 0;
}

Sau khi chạy ta có kết quả:

Tạm kết

Vậy là chúng ta đã hiểu thêm 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 kế thừa. 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.