Hướng dẫn multiple inheritance python

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.

Multiple Inheritance in Python

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.

Multilevel Inheritance in Python

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.

Visualizing Multiple Inheritance in Python
# 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é.

Chủ Đề