1. Kế thừa (Inheritance) trong Python

Kế thừa (Inheritance) trong lập trình hướng đối tượng Python là việc cho phép một lớp (hay class) sử dụng lại các thuộc tính và phương thức từ các lớp khác đã được định nghĩa. Các lớp con trong Python sẽ khai báo việc kế thừa một lớp cha ngay trong phần khai báo class và sử dụng khai báo việc kế thừa thông qua việc truyền tên của lớp cha (lớp cần kế thừa) vào trong phần đầu class. Ví dụ:  class SinhVien(ConNguoi) để khai báo lớp SinhVien kế thừa lớp ConNguoi.

Lớp được định nghĩa trước để cho các lớp khác kế thừa sẽ thường được gọi là lớp cha (hoặc có thể gọi là lớp cơ sở), lớp mới phát sinh và kế thừa lớp đã được định nghĩa trước sẽ được gọi là lớp con (hoặc có thể gọi là lớp dẫn xuất). Khi một lớp con kế thừa lớp cha thì lớp con sẽ có thể có tất cả các thuộc tínhphương thức của lớp cha. Ngoài ra lớp con cũng có thể mở rộng các thành phần kế thừa từ lớp cha và bổ sung thêm các thành phần mới.

Ví dụ dưới đây, khai báo lớp cha có tên ConNguoi bao gồm các thuộc tính: HoTen, Tuoi, GioiTinh và bao gồm các phương thức: an(), noi(), hoc(). Tiếp theo, khai báo lớp có tên SinhVien – lớp này sẽ kế thừa lớp ConNguoi và có thêm các phương thức: Msv, DiemTongKet và các phương thức: DangKyMon(), XepLoai() như bên dưới:

class ConNguoi:
    def __init__(self, ten, tuoi, gioitinh):
        # Khai bao cac thuoc tinh ConNguoi
        self.HoTen = ten
        self.Tuoi = tuoi
        self.GioiTinh = gioitinh
    # Khai bao cac phuong thuc ConNguoi
    def an(self):
        print(self.HoTen + " co the an!")
    def noi(self):
        print(self.HoTen + " co the noi!") 
    def hoc(self):
        print(self.HoTen + " co the hoc!")        

# Khai bao lop SinhVien ke thua lop ConNguoi
class SinhVien(ConNguoi):
    # Khai bao thuoc tinh lop SinhVien
    def __init__(self, msv, dtk, xl):
        # Khai bao cac thuoc tinh SinhVien
        self.MaSinhVien = msv
        self.DiemTongKet = dtk
        self.XepLoai = xl
    # Khai bao cac phuong thuc SinhVien
    def DangKyMon(self):
        print("Sinh vien " + self.HoTen + " co the dang ky mon!")
    def DanhGia(self):
        print("Sinh vien " + self.HoTen + " xep loai " + self.XepLoai) 

# Khoi tao doi tuong sv1 tu lop SinhVien
sv1 = SinhVien(208102103, 9.5, "gioi")

# Truy cap cac thuoc tinh trong lop ConNguoi thong qua lop SinhVien
sv1.HoTen = "Chu Minh Nam"
sv1.Tuoi = 20
sv1.GioiTinh = "nam"

print("Ho Ten SV: {0}".format(sv1.HoTen))
print("Tuoi SV: {0}".format(sv1.Tuoi))
print("Gioi Tinh SV: {0}".format(sv1.GioiTinh))

# Truy cap cac phuong thuc trong lop ConNguoi thong qua lop SinhVien
sv1.an()
sv1.noi()
sv1.hoc()

# Truy cap cac thuoc tinh lop SinhVien
print("MSV: {0}".format(sv1.MaSinhVien))
print("DTK: {0}".format(sv1.DiemTongKet))

# Truy cap cac phuong thuc lop SinhVien
sv1.DangKyMon()
sv1.DanhGia()

Kết quả:

Ho Ten SV: Chu Minh Nam
Tuoi SV: 20
Gioi Tinh SV: nam
Chu Minh Nam co the an!
Chu Minh Nam co the noi!
Chu Minh Nam co the hoc!
MSV: 208102103
DTK: 9.5
Sinh vien Chu Minh Nam co the dang ky mon!
Sinh vien Chu Minh Nam xep loai gioi

Trong ví dụ trên, ta thấy rằng lớp SinhVien đã kế thừa lớp ConNguoi. Khi tạo mới một đối tượng cho lớp SinhVien ta hoàn toàn có thể gọi và sử dụng lại các thuộc tính và phương thức có trong cả hai lớp đó là SinhVienConNguoi thông qua đối tượng sv1. Trong lớp SinhVien ta cũng có thể gọi trực tiếp các thuộc tính có trong lớp ConNguoi vào để sử dụng cho lớp SinhVien. Ví dụ như câu lệnh này:

def DangKyMon(self):
    print("Sinh vien " + self.HoTen + " co the dang ky mon!")

Thuộc tính HoTen nằm trong lớp ConNguoi nhưng lại có thể sử dụng được trong phương thức DangKyMon() của lớp SinhVien bởi vì tính kế thừa.

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

Đa kế thừa là việc một lớp cha được kế thừa bởi nhiều hai hoặc nhiều hơn các lớp con. Khi các lớp con (lớp dẫn xuất) kế thừa một lớp cha (lớp cơ sở) thì tất cả các thuộc tính, phương thức của lớp cha cũng đều có thể thực hiện và sử dụng trong các lớp con.

Xem minh họa dưới đây để hiểu rõ hơn đa kế thừa trong Python:

Hình trên, cho thấy rằng lớp Con Người là lớp chađược kế thừa bởi các lớp Sinh Viên, Giảng Viên và lớp Kỹ Sư. Như vậy, lớp Con Người3 lớp con được kế thừa và chúng ta gọi việc kế thừa này là đa kế thừa!

Ví dụ dưới đây, miêu tả việc đa kế thừa thông qua lớp ConNguoi làm lớp cha (lớp cơ sở) và các lớp: SinhVien, GiangVien, KySu làm lớp con (lớp dẫn xuất) kế thừa từ lớp cha ConNguoi:

class ConNguoi:
    def __init__(self, ten, tuoi, gioitinh):
        # Khai bao cac thuoc tinh ConNguoi
        self.HoTen = ten
        self.Tuoi = tuoi
        self.GioiTinh = gioitinh      

# Khai bao lop SinhVien ke thua lop ConNguoi
class SinhVien(ConNguoi):
    def __init__(self, msv, dtk, xl):
        # Khai bao cac thuoc tinh SinhVien
        self.MaSinhVien = msv
        self.DiemTongKet = dtk
        self.XepLoai = xl

# Khai bao lop GiangVien ke thua lop ConNguoi
class GiangVien(ConNguoi):
    def __init__(self, mgv, cn, xlgv):
        # Khai bao cac thuoc tinh GiangVien
        self.MaGiangVien = mgv
        self.ChuyenNganh = cn
        self.XepLoaiGiangVien = xlgv

# Khai bao lop KySu ke thua lop ConNguoi
class KySu(ConNguoi):
    def __init__(self,mks,cv,xlks):
        self.MaKySu = mks
        self.ChucVu = cv
        self.XepLoaiKySu =xlks

# Khoi tao doi tuong sv1 tu lop SinhVien
sv1 = SinhVien(208102103, 9.5, "gioi")

# Truy cap cac thuoc tinh trong lop ConNguoi thong qua lop SinhVien
sv1.HoTen = "Chu Minh Nam"
sv1.Tuoi = 20
sv1.GioiTinh = "nam"

print("Ho Ten SV: {0}".format(sv1.HoTen))
print("Tuoi SV: {0}".format(sv1.Tuoi))
print("Gioi Tinh SV: {0}".format(sv1.GioiTinh))
print("MSV: {0}".format(sv1.MaSinhVien))
print("Diem Tong Ket: {0}".format(sv1.DiemTongKet))
print("Xep Loai SV: {0}\n".format(sv1.XepLoai))

# Khoi tao doi tuong gv1 tu lop GiangVien
gv1 = GiangVien(112056368, "Cong Nghe Thong Tin", "kha")

# Truy cap cac thuoc tinh trong lop ConNguoi thong qua lop SinhVien
gv1.HoTen = "Vu Van Dinh"
gv1.Tuoi = 40
gv1.GioiTinh = "nam"

print("Ho Ten GV: {0}".format(gv1.HoTen))
print("Tuoi GV: {0}".format(gv1.Tuoi))
print("Gioi Tinh GV: {0}".format(gv1.GioiTinh))
print("MGV: {0}".format(gv1.MaGiangVien))
print("Chuyen Nganh GV: {0}".format(gv1.ChuyenNganh))
print("Xep Loai GV: {0}\n".format(gv1.XepLoaiGiangVien))

# Khoi tao doi tuong ks1 tu lop KySu
ks1 = KySu(163569879, "Ky Su Xay Dung", "gioi")

# Truy cap cac thuoc tinh trong lop ConNguoi thong qua lop SinhVien
ks1.HoTen = "Tran Bao Huy"
ks1.Tuoi = 28
ks1.GioiTinh = "nam"

print("Ho Ten KS: {0}".format(ks1.HoTen))
print("Tuoi KS: {0}".format(ks1.Tuoi))
print("Gioi Tinh KS: {0}".format(ks1.GioiTinh))
print("MKS: {0}".format(ks1.MaKySu))
print("Chuc Vu KS: {0}".format(ks1.ChucVu))
print("Xep Loai KS: {0}".format(ks1.XepLoaiKySu))

Kết quả:

Ho Ten SV: Chu Minh Nam
Tuoi SV: 20
Gioi Tinh SV: nam
MSV: 208102103
Diem Tong Ket: 9.5
Xep Loai SV: gioi

Ho Ten GV: Vu Van Dinh
Tuoi GV: 40
Gioi Tinh GV: nam
MGV: 112056368
Chuyen Nganh GV: Cong Nghe Thong Tin
Xep Loai GV: kha

Ho Ten KS: Tran Bao Huy
Tuoi KS: 28
Gioi Tinh KS: nam
MKS: 163569879
Chuc Vu KS: Ky Su Xay Dung
Xep Loai KS: gioi

Trong ví dụ trên, các lớp SinhVien, GiangVien, KySu đã kế thừa từ lớp cha ConNguoi. Vì vậy, khi khai báo các đối tượng sv1, gv1, ks1 thì đều có thể sử dụng các thuộc tính chung của lớp ConNguoi và các thuộc tính riêng của từng lớp.

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

Kế thừa đa cấp là việc các lớp con mới được tạo ra sẽ kế thừa các lớp con mà đã thực hiện kế thừa một lớp cha được định nghĩa trước. Việc kế thừa đa cấp này được hiểu như mối quan hệ giữa các thế hệ trong một gia đình. Đó là mối quan hệ ông–>cha–>con.

Xem hình minh họa bên dưới đây để hiểu rõ hơn về kế thừa đa cấp trong Python.

Hình trên, cho thấy rằng lớp Con Người lớp cha và được kế thừa bởi lớp Sinh Viên. Sau đó lớp Sinh Viên lại được coi là lớp cha và được kế thừa bởi lớp Lớp Trưởng. Như vậy, lớp Con Người có lớp con là Sinh Vien, lớp Sinh Viên lại có lớp con là Lớp Trường chúng ta gọi việc kế thừa này là kế thừa đa cấp!

Ví dụ dưới đây, sử khai báo 3 lớp: ConNguoi, SinhVien, LopTruong. Trong đó lớp SinhVien kế thừa lớp ConNguoi và lớp LopTruong sẽ kế thừa lớp SinhVien để tạo ra một kế thừa đa cấp ConNguoi–>SinhVien–>LopTuong

class ConNguoi:
    def __init__(self, ten, tuoi, gioitinh):
        # Khai bao cac thuoc tinh ConNguoi
        self.HoTen = ten
        self.Tuoi = tuoi
        self.GioiTinh = gioitinh      

# Khai bao lop SinhVien ke thua lop ConNguoi
class SinhVien(ConNguoi):
    def __init__(self, msv, dtk, xl):
        # Khai bao cac thuoc tinh SinhVien
        self.MaSinhVien = msv
        self.DiemTongKet = dtk
        self.XepLoai = xl

# Khai bao lop LopTruong ke thua lop SinhVien
class LopTruong(SinhVien):
    def __init__(self, lh, nv):
        # Khai bao cac thuoc tinh LopTruong
        self.LopHoc = lh
        self.NhiemVu = nv

# Khoi tao doi tuong lt1 tu lop LopTruong
lt1 = LopTruong("D15CNTT2","Quan Ly Lop Hoc")

# Truy cap cac thuoc tinh trong lop ConNguoi thong qua lop LopTruong
lt1.HoTen = "Tran Ngoc Ha"
lt1.Tuoi = 20
lt1.GioiTinh = "nu"
print("Ho Ten LT: {0}".format(lt1.HoTen))
print("Tuoi LT: {0}".format(lt1.Tuoi))
print("Gioi Tinh LT: {0}".format(lt1.GioiTinh))

# Truy cap cac thuoc tinh trong lop SinhVien thong qua lop LopTruong
lt1.MaSinhVien = 265463215
lt1.DiemTongKet = 10
lt1.XepLoai = "gioi"
print("MSV: {0}".format(lt1.MaSinhVien))
print("Diem Tong Ket: {0}".format(lt1.DiemTongKet))
print("Xep Loai SV: {0}".format(lt1.XepLoai))

# Truy cap cac thuoc tinh co trong lop LopTruong
print("Lop hoc: {0}".format(lt1.LopHoc))
print("Nhiem vu: {0}".format(lt1.NhiemVu))

Kết quả:

Ho Ten LT: Tran Ngoc Ha
Tuoi LT: 20
Gioi Tinh LT: nu
MSV: 265463215
Diem Tong Ket: 10
Xep Loai SV: gioi
Lop hoc: D15CNTT2
Nhiem vu: Quan Ly Lop Hoc

Trong ví dụ trên, lớp SinhVien kế thừa lớp ConNguoi và lớp LopTruong lại kế thừa lớp SinhVien. Như vậy, lớp LopTruong sẽ được coi là kế thừa cả hai lớp SinhVienConNguoi. Vì thế nên, khi khai báo đối tượng lt1 thì đối tượng này đều có thể sử dụng các thuộc tính của cả hai lớp ConNguoi và lớp SinhVien ngoài ra, đối tượng này còn sử dụng được các thuộc tính của chính nó.