Tìm Hiểu Cơ Chế Abstract Class Và Giao Tiếp Kế Thừa Trong Python

Khái Niệm Cơ Bản Về Lớp Trừu Tượng

Nếu như các class thông thường mô tả cấu trúc của một nhóm đối tượng cụ thể với các thuộc tính và hành vi chung, thì Abstract Class (lớp trừu tượng) lại đóng vai trò là khuôn mẫu cho các class khác. Nó tập hợp những đặc điểm cốt lõi mà các lớp con bắt buộc phải tuân thủ.

Các Đặc Điểm Kỹ Thuật Chính

  • Abstract class luôn cần chứa ít nhất một phương thức chưa được triển khai cụ thể (abstract method), tuy nhiên nó vẫn có thể chứa các phương thức bình thường đã có định nghĩa.
  • Bên trong abstract class, các abstract method chỉ khai báo chữ ký mà không có thân hàm thực thi cụ thể.
  • Về mặt ngữ nghĩa, bạn không thể tạo ra một thể hiện (instance) trực tiếp từ abstract class này.
  • Quan trọng nhất: Khi viết lớp con (subclass) kế thừa từ abstract class, chương trình sẽ yêu cầu lớp con phải định nghĩa đầy đủ tất cả các phương thức trừu tượng trước khi cho phép khởi tạo đối tượng.

Ví Dụ Về Class Thông Thường

Xét trường hợp dưới đây, ta định nghĩa một lớp cha tiêu chuẩn không sử dụng thư viện hỗ trợ trừu tượng:

# -*- coding: utf-8 -*-

class BaseUser(object):
    """Lớp cha mặc định không có cơ chế ép buộc"""
    
    def __init__(self, user_role, full_name, access_level):
        self.user_role = user_role
        self.full_name = full_name
        self.access_level = access_level

    # Phương thức đã được định nghĩa sẵn
    def execute_command(self):
        print("Executing default command...")

    # Phương thức rỗng, không bắt buộc phải override
    def custom_behavior(self):
        pass

# Lớp con kế thừa
class AdminUser(BaseUser):
    # Ghi đè phương thức kiểm tra quyền
    def check_permission(self):
        print("Admin Access Granted")

# Khởi tạo đối tượng
user_instance = AdminUser(user_role="admin", full_name="Nguyen Van A", access_level=5)
user_instance.execute_command()

Như bạn thấy, dù lớp cha BaseUser có một phương thức custom_behavior chưa làm gì cả (chỉ pass), nhưng việc tạo instance từ lớp con AdminUser vẫn diễn ra bình thường. Đây là cách hoạt động của class thường, không áp đặt quy tắc ép buộc.

Ví Dụ Về Abstract Class Gây Lỗi

Khi sử dụng module abc, chúng ta chuyển sang cơ chế ép buộc hợp đồng giao diện:

# -*- coding: utf-8 -*-
from abc import ABC, abstractmethod

class BaseSystem(ABC):
    """Abstract class yêu cầu kế thừa nghiêm ngặt"""
    
    def __init__(self, system_id, config_map):
        self.system_id = system_id
        self.config_map = config_map

    # Phương thức thường
    def log_info(self):
        print("Logging system info...")

    # Phương thức trừu tượng bắt buộc
    @abstractmethod
    def initialize_module(self):
        pass

# Lớp con bỏ sót phương thức abstract
class TestSystem(BaseSystem):
    def log_info(self):
        print("Custom logging enabled")

# Sẽ phát sinh lỗi khi cố gắng tạo instance
try:
    sys_obj = TestSystem(system_id="T01", config_map={"debug": True})
except TypeError as err:
    print(f"Lỗi xảy ra: {err}")

Đoạn mã trên sẽ dừng lại ở dòng khởi tạo đối tượng. Lý do là lớp TestSystem chưa cung cấp cài đặt cụ thể cho phương thức initialize_module được đánh dấu bởi @abstractmethod. Python không cho phép biến đổi lớp trừu tượng thành đối tượng sống nếu giao diện chưa hoàn thiện.

Thực Hiện Đúng Quy Trình

Để khắc phục vấn đề trên và hoàn thành giao diện lớp con, ta cần định nghĩa lại các phương thức trừu tượng:

# -*- coding: utf-8 -*-
from abc import ABC, abstractmethod

class BaseSystem(ABC):
    def __init__(self, system_id, config_map):
        self.system_id = system_id
        self.config_map = config_map

    def log_info(self):
        print("Logging system info...")

    @abstractmethod
    def initialize_module(self):
        pass

class ProductionSystem(BaseSystem):
    # Ghi đè phương thức thông thường
    def log_info(self):
        print("Production mode logging active.")
        
    # Bắt buộc phải định nghĩa để thỏa mãn điều kiện trừu tượng
    def initialize_module(self):
        print(f"Module initialized for ID: {self.system_id}")

# Khởi tạo thành công
sys_prod = ProductionSystem(system_id="P99", config_map={"secure": True})
sys_prod.log_info()       # Production mode logging active.
sys_prod.initialize_module() # Module initialized for ID: P99

Thẻ: python abstract-class oop abc-module inheritance

Đăng vào ngày 19 tháng 5 lúc 00:33