Python Multiple Inheritance
A class can be derived from more than one base class in Python, similar to C++. This is called multiple inheritance.
In multiple inheritance, the features of all the base classes are inherited into the derived class. The syntax for multiple inheritance is similar to single inheritance.
Example
class Base1:
pass
class Base2:
pass
class MultiDerived[Base1, Base2]:
pass
Here, the MultiDerived class is derived from Base1 and Base2 classes.
The MultiDerived class inherits from both Base1 and Base2 classes.
Python Multilevel Inheritance
We can also inherit from a derived class. This is called multilevel inheritance. It can be of any depth in Python.
In multilevel inheritance, features of the base class and the derived class are inherited into the new derived class.
An example with corresponding visualization is given below.
class Base:
pass
class Derived1[Base]:
pass
class Derived2[Derived1]:
pass
Here, the Derived1 class is derived from the Base class, and the Derived2 class is derived from the Derived1 class.
Method Resolution Order in Python
Every class in Python
is derived from the object
class. It is the most base type in Python.
So technically, all other classes, either built-in or user-defined, are derived classes and all objects are instances of the object
class.
# Output: True
print[issubclass[list,object]]
# Output: True
print[isinstance[5.5,object]]
# Output: True
print[isinstance["Hello",object]]
In the multiple inheritance scenario, any specified attribute is searched first in the current class. If not found, the search continues into parent classes in depth-first, left-right fashion without searching the same class twice.
So, in the above example of
MultiDerived
class the search order is [MultiDerived
, Base1
, Base2
, object
]. This order is also called linearization of MultiDerived
class and the set of rules used to find this order is called Method Resolution Order [MRO].
MRO must prevent local precedence ordering and also provide monotonicity. It ensures that a class always appears before its parents. In case of multiple parents, the order is the same as tuples of base classes.
MRO of a class can be
viewed as the __mro__
attribute or the mro[]
method. The former returns a tuple while the latter returns a list.
>>> MultiDerived.__mro__
[,
,
,
]
>>> MultiDerived.mro[]
[,
,
,
]
Here is a little more complex multiple inheritance example and its visualization along with the MRO.
# Demonstration of 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:
# [, ,
# , ,
# , ,
# ]
print[M.mro[]]
Output
[, , , , , , ]
To know the actual algorithm on how MRO is calculated, visit Discussion on MRO.
Khi chúng ta muốn mở rộng một lớp [class] hiện có, chúng ta có thể sửa đổi lớp đó. Nhưng như thế có thể dẫn đến việc gây lỗi hoặc ảnh hưởng đến những đối tượng khác. Chúng ta cũng có thể tạo mới một class, copy những gì đang có và viết thêm mới những tính năng mà chúng ta mong muốn. Nhưng như thế thì code của chúng ta lại thừa và khó bảo trì.
Vậy giải pháp là kế thừa
[Inheritance]
Nội dung của bài
- 1 Kế thừa [Inheritance] là gì?
- 2 Định nghĩa một lớp cơ sở [ base class]
- 3 Định nghĩa một lớp con [subclassing]
- 3.1 Ghi đè nên chức năng hiện có – Override a Method
- 3.2 Thêm một phương thức mới
- 3.3 Hàm super[]
- 4 Kế thừa từ nhiều lớp cơ sở – Multiple Inheritance
- 5 Video demo
- 6 Tổng kết
Kế thừa [Inheritance] là gì?
Kế thừa là quá trình tạo một class mới từ một class cũ. Một lớp được tạo thông qua kế thừa sẽ thừa hưởng toàn bộ code của lớp cũ [ như các thuộc tính, các phương thức].
Khi một class kế thừa từ một class khác, class kế thừa được gọi là class con hay class dẫn xuất. Class được kế thừa gọi là class cha hoặc class cơ sở.
Định nghĩa một lớp cơ sở [ base class]
Một lớp không kế thừa từ một lớp nào khác gọi là lớp cơ sở.
class Animal:
def description[self]:
print["I'm an Animal!"]
Ví dụ trên chúng ta thử áp dụng tư thực tế, chúng ta xây dựng lớp động vật là lớp cơ sở cho các loại động vật: chó, mèo…
Định nghĩa một lớp con [subclassing]
class Animal:
def description[self]:
print["I'm an Animal!"]
class Dog[Animal]:
pass
Tạo một lớp mới kế thừa từ lớp cơ sở gọi là lớp con. Trong lớp con chúng ta có thể thêm mới chức năng hoặc ghi đè chức năng hiện có.
Giờ chúng ta thử tạo ra đối tượng từ class Dog:
class Animal:
def description[self]:
print["I'm an Animal!"]
class Dog[Animal]:
pass
an = Animal[]
shiba = Dog[]
an.description[]
# prints I'm an Animal!
shiba.description[]
# prints I'm an Animal!
Lớp Dog đang kế thừa hoàn toàn các chức năng của lớp Animal và chưa có thay đổi gì. Nên khi chúng ta gọi đến phương thức description[] ở hai đối tượng shiba và an thì đều cho kết quả giống nhau.
Ghi đè nên chức năng hiện có – Override a Method
class Animal:
def description[self]:
print["I'm an Animal!"]
class Dog[Animal]:
def description[self]:
print["I'm a dog!"]
an = Animal[]
shiba = Dog[]
an.description[]
# prints I'm an Animal!
shiba.description[]
# prints I'm a dog!
Trong lớp con chúng ta đã khai báo phương thức description[] có cùng tên với phương thức của lớp cơ sở. Nên khi chúng ta thực hiện lời gọi shiba.description[], phương thức trong lớp con được thực thi.
Thêm một phương thức mới
Lớp con cũng có thể định nghĩa một phương thức mới chưa có trong lớp cơ sở.
class Animal:
def description[self]:
print["I'm an Animal!"]
class Dog[Animal]:
def description[self]:
print["I'm a dog!"]
def bark[self, times]:
print[f'{"woof! " * times}']
shiba = Dog[]
shiba.bark[3]
# prints woof! woof! woof!
Phương thức bark[] chỉ có trong lớp Dog mà không có trong lớp Animal.
Hàm super[]
Đôi khi bạn ghi đè một phương thức của lớp cơ sở nhưng muốn sử dụng lại phương thức của lớp cơ sở và thêm vào một số tính năng mới. Bạn có thể sử dụng hàm super[] để làm điều này.
# base class
class Animal[]:
def __init__[self, color]:
self.color = color
def description[self]:
print["I'm a", self.color, "Animal"]
# subclass
class Dog[Animal]:
def __init__[self, color, foots]:
super[].__init__[color] # invoke Animal’s __init__[] method
self.foots = foots
def description[self]:
print["I'm a", self.color, "dog and I have", self.foots, "foots!"]
# create an object from each class
an = Animal['White']
shiba = Dog['Black', 4]
an.description[]
# Prints I'm a White Animal
shiba.description[]
# Prints I'm a Black dog, I have 4 foots
Kế thừa từ nhiều lớp cơ sở – Multiple Inheritance
Python cho phép một lớp có thể kế thừa từ nhiều lớp cở sở.
class Animal:
def description[self]:
print["I'm an Animal!"]
class FlyingAnimal:
def fly[self]:
print["I can fly!"]
class Bird[Animal, FlyingAnimal]:
pass
bird = Bird[]
bird.description[]
# prints I'm an Animal!
bird.fly[]
# prints I can fly!
Lớp con Bird kế toàn tất cả các phương thức của lớp Animal và FlyingAnimal.
Video demo
Tổng kết
Thừa kế là kiến thức rất quan trọng trong lập trình hướng đối tượng. Các bạn hãy thực hành thật tốt phần này nhé.