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

Ở bài học trước chúng ta đã cùng tìm hiểu về Kế thừa trong lập trình hướng đối tượng của ngôn ngữ Python. Kế thừa cho phép chúng ta khai báo lớp mới sử dụng lại các hàm và thuộc tính của lớp cha cùng các chức năng mở rộng thêm. Trong bài viết này, chúng ta sẽ tiếp tục bài học cùng chủ đề Kế thừa nhưng ở mức độ sâu sắc hơn, đó là Đa kế thừa và thứ tự truy xuất phương thức của các lớp cha (Method Resolution Order).

Đa kế thừa (Multiple Inheritance)

Giống như C++ thì trong Python một lớp có thể được định nghĩa từ nhiều lớp cha. Điều này được gọi là đa kế thừa.

Cú pháp:

class LopCha1:
pass

class LopCha2:
pass

class LopCon(LopCha1, LopCha2):
pass

Lớp con đươc định nghĩa từ nhiều lớp cha và kế thừa đặc tính của cả hai lớp.

Các lớp cha có thể có các thuộc tính hoặc các phương thức giống nhau. Lớp con sẽ ưu tiên thừa kế thuộc tính, phương thức của lớp đứng đầu tiên trong danh sách thừa kế.

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

Ngoài việc có thể kế thừa từ các lớp cha, bạn còn có thể tạo lớp con mới kế thừa các lớp con trước đó. Đây gọi là kế thừa đa cấp (Multilevel Inheritance).

Với trường hợp này, các đặc tính của lớp cha và lớp con trước đó sẽ được lớp con mới kế thừa.

Cú pháp:

class LopCha:
pass

class LopCon1(LopCha):
pass

class LopCon2(LopCon1):
pass

LopCon1 kế thừa LopCha, LopCon2 kế thừa LopCon1.

Thứ tự truy xuất phương thức (Method Resolution Order)

Class được bắt nguồn từ object. Trong kịch bản đa thừa kế, bất kỳ thuộc tính cần được truy xuất nào, đầu tiên sẽ được tìm kiếm trong lớp hiện tại. Nếu không tìm thấy, tìm kiếm tiếp tục vào lớp cha đầu tiên và từ trái qua phải.

Vậy thứ tự truy xuất sẽ là [LopCon, LopCha1, LopCha2, object].

Thứ tự này còn được gọi là tuyến tính hóa của LopCon và tập hợp các quy tắc được sử dụng để tìm thứ tự này được gọi là Thứ tự truy xuất phương thức (MRO).

Nói một cách dễ hiểu, MRO dùng để hiển thị danh sách/tuple các class cha của một class nào đó.

MRO được sử dụng theo hai cách:

  • __mro__: trả về một tuple
  • mro(): trả về một danh sách.

>>> LopCon.__mro__
(<class '__main__.LopCon'>,
<class '__main__.LopCha1'>,
<class '__main__.LopCha2'>,
<class 'object'>)

>>> LopCon.mro()
[<class '__main__.LopCon>,
<class '__main__.LopCha1'>,
<class '__main__.LopCha2'>,
<class 'object'>]

Dưới đây là một ví dụ thừa kế phức tạp và hiển thị trực quan của nó cùng với MRO.

class X: pass
class Y: pass
class Z: pass

class A(X,Y): pass
class B(Y,Z): pass

class M(B,A,Z): pass

# Output:
# [<class '__main__.M'>, <class '__main__.B'>,
# <class '__main__.A'>, <class '__main__.X'>,
# <class '__main__.Y'>, <class '__main__.Z'>,
# <class 'object'>]

Leave a Reply