1. Tính trừu tượng (Abstract) trong Python

Tính trừu tượng (Abstract) là tính chất chỉ đưa ra các thành phần trong một đối tượng mà không hề thực hiện hành động gì với thành phần đó. Việc này cho phép chúng ta tạo ra các phương thức trừu tượng trong một lớp – khi một lớp có nhiều các phương thức trừu tượng thì lớp đó được gọi là lớp trừu tượng.

Phương thức trừu tượng trong một lớp là phương thức có phần khai báo nhưng không có phần thân để thực thi. Khi các lớp con kế thừa một lớp trừu tượng, bắt buộc các lớp con đó phải gọi ra và sử dụng các phương thức trừu tượng của lớp cha đã khai báo trước.

Một ví dụ đơn giản, khi khai báo một phương thức trong một lớp nhưng phần thân của phương thức lại không thực thi điều gì:

class DongVat():
    # Dinh nghia cac phuong thuc truu tuong trong lop DongVat
    def DiChuyen(self):
        pass
    def AnUong(self):
        pass

class ConNguoi(DongVat):
    # Su dung lai cac phuong thuc cua lop DongVat
    def DiChuyen(self):
        print("Con nguoi co the di chuyen!")
    def AnUong(self):
        print("Con nguoi co the an uong!")

# Khoi tao doi tuong p1 tu lop ConNguoi
p1 = ConNguoi()
p1.DiChuyen()
p1.AnUong()

Kết quả:

Con nguoi co the di chuyen!
Con nguoi co the an uong!

Ví dụ trên, ta thấy rằng các phương thức DiChuyen(), AnUong() trong lớp DongVat mặc dù được khai báo trong lớp, tuy nhiên phần thân của các phương thức này lại là từ khóa pass. Việc này cho thấy các phương thức trên là các phương thức trừu tượng vì chỉ có phần khai báo nhưng không có phần thực thi.

2. Trừu tượng phương thức trong Python

Trừu tượng phương thức là việc khai báo một phương thức trong một lớp mà không có phần thực thi. Các phương thức trừu tượng thường được đặt trong lớp cha để các lớp con kế thừa phải gọi lại và sử dụng các phương thức trừu tượng đó.

Trong Python, để sử dụng được việc khai báo trừu tượng cho một phương thức trong lớp, khi đó ta cần khai báo mô-đun abc sau đó nhập vào các lớp cơ sở trừu tượng ABC, và các phương thức trừu tượng abstractmethod có trong mô-đun đó bằng câu lệnh sau:

from abc import ABC, abstractmethod

Khi cần sử dụng trừu tượng cho một phương thức trong class, khi đó ta cần kế thừa lớp ABS và sử dụng từ khóa @abstractmethod đặt bên trên phương thức cần khai báo là trừu tượng:

from abc import ABC,abstractmethod

# Khai bao lop DongVat ke thua lop truu tuong ABC 
class DongVat(ABC):
    # Khai bao phuong thuc truu tuong
    @abstractmethod
    def DiChuyen(self):
        pass
    @abstractmethod
    def AnUong(self):
        pass

# Khai bao lop ConNguoi ke thua lop DongVat
class ConNguoi(DongVat):
    # Goi va su dung cac phuong thuc truu tuong trong lop DongVat
    def DiChuyen(self):
        print("Con nguoi co the di chuyen!")
    def AnUong(self):
        print("Con nguoi co the an uong!")

# Khoi tao doi tuong p1 tu lop ConNguoi 
p1 = ConNguoi() 
p1.DiChuyen() 
p1.AnUong()

Kết quả:

Con nguoi co the di chuyen!
Con nguoi co the an uong!

Lưu ý: Khi một lớp con kế thừa lớp cha có các phương thức trừu tượng, nếu như lớp con kế thừa lớp cha có phương thức trừu tượng mà không gọi và sử dụng các phương thức trừu tượng của lớp cha thì chương trình sẽ gây ra lỗi:

from abc import ABC,abstractmethod

# Khai bao lop DongVat ke thua lop truu tuong ABC 
class DongVat(ABC):
    # Khai bao phuong thuc truu tuong
    @abstractmethod
    def DiChuyen(self):
        pass
    @abstractmethod
    def AnUong(self):
        pass

# Khai bao lop ConNguoi ke thua lop DongVat
class ConNguoi(DongVat):
    # Khoi tao cac phuong thuc trong lop ConNguoi
    def Hoc(self):
        print("Con nguoi co the hoc!")
    def Noi(self):
        print("Con nguoi co the noi!")

# Khoi tao doi tuong p1 tu lop ConNguoi 
p1 = ConNguoi() 
p1.Hoc() 
p1.Noi()

Kết quả:

Traceback (most recent call last):
  File "d:\laptrinhtudau\python\main.py", line 22, in <module>
    p1 = ConNguoi()
TypeError: Can't instantiate abstract class ConNguoi with abstract methods AnUong, DiChuyen

Chương trình trên gây ra lỗi bởi vì, các phương thức trừu tượng được khai báo trong lớp cha DongVat thế nhưng trong lớp con ConNguoi lại không gọi ra và sử dụng các phương thức trừu tượng đó!

3. Lớp trừu tượng trong Python

Các lớp trừu tượng là không đầy đủ các thành phần bởi vì chúng có các phương thức chỉ được khai báo mà không có phần thân. Việc này nghĩa là các lớp trừu tượng được tạo ra chỉ để làm các khuân mẫu (template) cho các lớp con kế thừa phải tuân theo khuân mẫu đó.

Trong Python, một lớp trừu tượng không phải là một lớp cụ thể, nó không thể được khởi tạo từ một đối tượng bên ngoài. Khi chúng ta cố tình khởi tạo ra một đối tượng cho lớp trừu tượng, chương trình sẽ gây ra lỗi.

from abc import ABC,abstractmethod, abstractproperty

# Khai bao lop DongVat ke thua lop truu tuong ABC 
class DongVat(ABC):
    # Khai bao phuong thuc truu tuong
    @abstractmethod
    def DiChuyen(self):
        pass
    @abstractmethod
    def AnUong(self):
        pass

# Khoi tao doi tuong dv tu lop DongVat
dv = DongVat()
# Truy cap vao cac phuong thuc truu tuong co trong lop DongVat
dv.DiChuyen()
dv.AnUong()

Kết quả:

Traceback (most recent call last):
  File "d:\laptrinhtudau\python\main.py", line 15, in <module>
    dv = DongVat()
TypeError: Can't instantiate abstract class DongVat with abstract methods AnUong, DiChuyen

Chạy chương trình trên gây ra lỗi, bởi vì các lớp trừu tượng trong lớp DongVat không được phép gọi ra sử dụng ở bên ngoài lớp. Theo định nghĩa trên, các lớp trừu tượng thực chất không tồn tại là một lớp cụ thể và không thể khởi tạo lớp này từ đối tượng dv. Nó chỉ có thể được gọi ra và sử dụng thông qua các đối tượng có lớp kế thừa các phương thức trừu tượng đó.