1. Tính đa hình (Polymorphism) trong Python

Tính đa hình (Polymorphism) là tính chất biến hóa theo nhiều hình thức trong lập trình hướng đối tượng, tính chất này dựa theo khái niệm cho phép hai hoặc nhiều lớp có những phương thức giống nhau nhưng có thể thực thi theo những cách thức khác nhau. Việc đa hình cho thấy sự đa dạng trong mỗi một lớp, không nhất thiết rằng các lớp có phương thức giống nhau là phải thực hiện các các hành động giống nhau.

Trong ngôn ngữ lập trình Python, chúng ta có thể đã sử dụng tính đa hình thông qua một số hàm, phương thức mà Python đã xây dựng sẵn. Ví dụ đơn giản chính là hàm len() – hàm này được sử dụng để trả về độ dài của một biến, list, tuple… Nghĩa là hàm này có thể sử dụng tương thích cho nhiều kiểu dữ liệu khác nhau.

print(len("Laptrinhtudau.com"))
print(len(["Python", "Java", "C++"]))
print(len({"name": "Chu Minh Nam", "age": 20, "sex":"nam"}))

Kết quả:

17
3
3

Ngoài ra, người lập trình viên cũng có thể tự khởi tạo một số hàm có tính đa hình. Ví dụ như hàm tính tổng dưới đây:

def tong(x, y, z = 0):
    return x + y + z
 
print(tong(1, 2))
print(tong(1, 2, 3))

Kết quả:

3
6

Đặc điểm chính của các hàm, phương thức có sử dụng tính đa hình đó là chúng đều có cùng tên hàm thế nhưng các tham số được truyền vào hàm lại có thể có kiểu dữ liệu khác nhau hoặc số lượng các tham số truyền vào hàm có thể không bằng nhau.

2. Đa hình phương thức trong các lớp Python

Trong hai hoặc nhiều lớp khác nhau trong chương trình Python, có thể tồn tại các phương thức có cùng tên giống nhau. Thế nhưng, việc thực hiện các phương thức trong mỗi lớp khác nhau, sẽ thực hiện hành động khác nhau. Khi đó chính là việc thực hiện theo tính đa hình trong các phương thức có trong các lớp.

Ví dụ dưới đây, khai báo hai lớp có tên là: VietNam, TrungQuoc. Trong đó, lớp VietNam và TrungQuoc sẽ đều có chung các phương thức là: ThuDo(), NgonNgu(), KhuVuc() thế nhưng trong mỗi phương thức của từng lớp trên lại thực hiện theo mỗi cách khác nhau mặc dù tên của các phương thức có trong hai lớp là đều trùng nhau.

class VietNam():
    def ThuDo(self):
        print("Thu do cua Viet Nam la Ha Noi!")
 
    def NgonNgu(self):
        print("Ngon ngu cua Viet Nam la Tieng Viet!")
 
    def KhuVuc(self):
        print("Khu vuc cua Viet Nam la Dong Nam A!")
 
class TrungQuoc():
    def ThuDo(self):
        print("Thu do cua Trung Quoc la Bac Kinh!")
 
    def NgonNgu(self):
        print("Ngon ngu cua Trung Quoc la Tieng Trung!")
 
    def KhuVuc(self):
        print("Khu vuc cua Trung Quoc la Dong Bac A!")

# Khai bao doi tuong vn tu lop VietNam
vn = VietNam()
# Thuc thi cac phuong thuc trong lop VietNam
vn.ThuDo()
vn.NgonNgu()
vn.KhuVuc()
print()

# Khai bao doi tuong tq tu lop TrungQuoc
tq = TrungQuoc()
# Thuc thi cac phuong thuc trong lop TrungQuoc
tq.ThuDo()
tq.NgonNgu()
tq.KhuVuc()

Kết quả:

Thu do cua Viet Nam la Ha Noi!
Ngon ngu cua Viet Nam la Tieng Viet!
Khu vuc cua Viet Nam la Dong Nam A! 

Thu do cua Trung Quoc la Bac Kinh!
Ngon ngu cua Trung Quoc la Tieng Trung!
Khu vuc cua Trung Quoc la Dong Bac A!

Trong ví dụ trên, mặc dù trong hai lớp VietNamTrungQuoc đều có các phương thức trùng tên với nhau, thế nhưng khi gọi để thực hiện các phương thức thông qua đối tượng vntq thì lại cho ra các kết quả khác nhau. Cho thấy sự đa hình giữa các phương thức có trong các lớp. Không nhất thiết các phương thức có cùng tên sẽ phải thực thi một công việc nào đó giống nhau!

3. Đa hình phương thức trong các lớp kế thừa Python

Tính đa hình trong Python, cho phép chúng ta định nghĩa các phương thức trong lớp con có cùng tên với các phương thức của lớp cha. Trong kế thừa, các lớp con sẽ được kế thừa các phương thức từ lớp cha. Tuy nhiên, có thể sửa đổi một phương thức trong lớp cha của nó bằng cách ghi đè lại các phương thức có cùng tên với các phương thức của lớp cha – việc ghi đè này được thực hiện bên trong lớp con. Đây còn được gọi là kỹ thuật Ghi đè phương thức trong lập trình hướng đối tượng.

Ví dụ dưới đây, khai báo lớp HinhVe bao gồm các thuộc tính: ChieuDai, ChieuRong và bao gồm các phương thức: TinhChuVi(), TinhDienTich(). Tiếp theo, khai báo lớp HinhChuNhat với các phương thức TinhChuVi()TinhDienTich() – 2 phương thức này được ghi đè lại theo 2 phương thức của lớp HinhVe như sau:

class HinhVe():
    # Khai bao cac thuoc tinh HinhVe
    def __init__(self):
        self.ChieuDai = 5
        self.ChieuRong = 7
    # Khai bao cac phuong thuc HinhVe
    def TinhChuVi(self):
        self.ChuVi = self.ChieuDai + self.ChieuRong
        print("Chu vi hinh ve la: {0}".format(self.ChuVi))

    def TinhDienTich(self):
        self.DienTich = (self.ChieuDai * self.ChieuRong) / 5
        print("Dien tich hinh ve la: {0}".format(self.DienTich))


class HinhChuNhat(HinhVe):
    # Ghi de phuong thuc cua lop cha HinhVe trong lop con HinhChuNhat
    def TinhChuVi(self):
        self.ChuVi = (self.ChieuDai + self.ChieuRong) * 2
        print("Chu vi hinh chu nhat la: {0}".format(self.ChuVi))

    def TinhDienTich(self):
        self.DienTich = self.ChieuDai * self.ChieuRong
        print("Dien tich hinh chu nhat la: {0}".format(self.DienTich))

# Khai bao doi tuong hv tu lop HinhVe
hv = HinhVe()
# Truy cap cac phuong thuc HinhVe
hv.TinhChuVi()
hv.TinhDienTich()
print()

# Khai bao doi tuong hcn tu lop HinhChuNhat
hcn = HinhChuNhat()
# Truy cap cac phuong thuc HinhChuNhat
hcn.TinhChuVi()
hcn.TinhDienTich()

Kết quả:

Chu vi hinh ve la: 12
Dien tich hinh ve la: 7.0

Chu vi hinh chu nhat la: 24
Dien tich hinh chu nhat la: 35

Trong ví dụ trên, chúng ta thấy rằng lớp cha HinhVe có hai phương thức TinhChuViTinhDienTich được thực thi và cho ra một kết quả khác với lớp con HinhChuNhat. Điều đó sảy ra bởi vì trong lớp con HinhChuNhat đã ghi đè lại hai phương thức của lớp cha và thực hiện phương thức TinhChuVi()TinhDienTich() theo một cách khác với cách của lớp cha của nó thực hiện.