Lớp và phương thức trừu tượng
Thuộc phần Lập trình hướng đối tượng trong hành trình Python của Coddy. Bài học 25 trên 64.
Lớp trừu tượng là những lớp không thể được khởi tạo trực tiếp và chứa các phương thức trừu tượng mà lớp con phải triển khai.
Hãy hình dung như một biểu mẫu: Lớp trừu tượng giống như một biểu mẫu bắt buộc, trong đó một số trường là bắt buộc (phương thức trừu tượng), còn một số trường là tùy chọn (phương thức cụ thể). Bạn không thể gửi chính biểu mẫu đó, bạn phải điền tất cả các trường bắt buộc trước. Tương tự, bạn không thể tạo đối tượng từ lớp trừu tượng cho đến khi lớp con triển khai tất cả các phương thức trừu tượng.
Nhập module abc để tạo lớp trừu tượng:
from abc import ABC, abstractmethodTạo một lớp trừu tượng có các phương thức trừu tượng:
class Shape(ABC):
@abstractmethod
def area(self):
pass
@abstractmethod
def perimeter(self):
pass
def describe(self):
return "This is a shape" # Phương thức cụ thể (có phần triển khai)Decorator @abstractmethod đánh dấu các phương thức mà lớp con phải triển khai. Đây là những "trường bắt buộc" trên biểu mẫu của bạn. Các phương thức thông thường như describe() có thể có phần triển khai và được kế thừa nguyên trạng. Đây là những "trường được điền sẵn".
Tại sao nên dùng lớp trừu tượng? Chúng buộc bạn tuân theo một quy ước. Nếu bạn tạo lớp Shape, nghĩa là bạn nói rằng “mọi hình dạng PHẢI tính được diện tích và chu vi”. Điều này ngăn lỗi do bạn quên triển khai các phương thức quan trọng.
Thử tạo một đối tượng thuộc lớp trừu tượng:
# Điều này sẽ gây ra lỗi:
# shape = Shape() # TypeError: Can't instantiate abstract classLỗi này xảy ra có chủ ý, giống như việc bạn gửi một biểu mẫu trống. Python đang báo rằng: “Bạn chưa điền các trường bắt buộc (phương thức area và perimeter)!”
Tạo một lớp con cụ thể triển khai tất cả các phương thức trừu tượng:
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14 * self.radius ** 2
def perimeter(self):
return 2 * 3.14 * self.radiusGiờ thì mình đã “điền đầy đủ các trường bắt buộc”, tức là đã triển khai cả area() và perimeter(). Lớp Circle giờ đã hoàn chỉnh, là một lớp cụ thể có thể tạo đối tượng.
Giờ bạn có thể tạo các đối tượng từ lớp cụ thể:
circle = Circle(5)
print(circle.area())
print(circle.perimeter())
print(circle.describe()) # Phương thức cụ thể kế thừa từ lớp chaTạo thêm một lớp con cụ thể:
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width self.height
def perimeter(self):
return 2 * (self.width + self.height)
rectangle = Rectangle(4, 6)
print(rectangle.area())
print(rectangle.perimeter())Đầu ra:
78.5
31.400000000000002
This is a shape
24
20Lớp trừu tượng định nghĩa một quy tắc mà các lớp con phải tuân theo. Dùng ABC và @abstractmethod để tạo lớp trừu tượng. Các lớp con phải triển khai tất cả phương thức trừu tượng, nếu không, chúng cũng sẽ là lớp trừu tượng. Điều này đảm bảo tính nhất quán và ngăn các phần triển khai chưa hoàn chỉnh.
Thử thách
Trung bìnhTrong thử thách này, bạn sẽ triển khai một hệ thống xử lý thanh toán.
Bạn cần hoàn thiện phần triển khai trong các tệp sau:
paymentmethod.py- Lớp cơ sở trừu tượng với logic xác thựccreditcard.py- Phần triển khai thanh toán bằng thẻ tín dụngpaypal.py- Phần triển khai thanh toán bằng PayPal
Làm theo các chú thích TODO trong từng tệp để triển khai chức năng cần thiết. Các chú thích sẽ hướng dẫn bạn từng bước tạo các phương thức trừu tượng, triển khai các lớp con cụ thể và thiết lập mối quan hệ nhập phù hợp giữa các tệp.
Tệp driver.py có các test case để kiểm tra phần triển khai của bạn hoạt động chính xác, xử lý nhiều tình huống thanh toán khác nhau và hiển thị thông tin phù hợp cho từng phương thức thanh toán.
Tự làm thử
from creditcard import CreditCard
from paypal import PayPal
# Kiểm tra các cách triển khai. KHÔNG SỬA ĐOẠN CODE KIỂM TRA NÀY
cc = CreditCard("1234567890123456")
pp = PayPal("user@example.com")
# Xử lý các khoản thanh toán hợp lệ
if cc.validate(100):
print(cc.process_payment(100))
print(cc.payment_details())
if pp.validate(200):
print(pp.process_payment(200))
print(pp.payment_details())
# Thử một số tiền không hợp lệ
if not pp.validate(0):
print("Invalid payment amount")
# Nếu bỏ dấu chú thích, dòng này sẽ gây lỗi:
# pm = PaymentMethod() # Không thể tạo instance của lớp trừu tượngBài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Lập trình hướng đối tượng
1Nền tảng về lập trình hướng đối tượng
Tệp bên ngoàiGiới thiệu về lập trình hướng đối tượngLớp và đối tượngTham số selfPhương thứcThuộc tínhPhương thức khởi tạo (__init__)Ôn tập: máy tính đơn giản4Kế thừa
Kế thừa cơ bảnHàm super()Ghi đè phương thứcKế thừa đa lớpThứ tự phân giải phương thứcÔn tập: hệ thống phân cấp nhân viên2Decorator
Giới thiệu về decoratorDecorator thuộc tínhDecorator phương thức tĩnhDecorator phương thức lớp5Tính đa hình
Xem lại cách ghi đè phương thứcKiểu gõ vịtLớp và phương thức trừu tượngThiết kế giao diệnÔn tập: máy tính hình học8Các khái niệm OOP nâng cao
Kết hợp và kế thừaMixinPhương thức tĩnh và phương thức lớpDecorator lớpTrình quản lý ngữ cảnhTự luyện tập: Trình biên dịch Python online