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ính và phươ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à SinhVien và ConNguoi 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 và đượ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ười có 3 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 Ho Ten KS: Tran Bao Huy |
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à 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 SinhVien và ConNguoi. 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ó.