在Python的面向对象编程中,抽象类是一种特殊的基类:它本身不能被实例化,核心作用是规定子类必须实现哪些方法。Python标准库提供了abc模块来支持抽象类,其中最核心的两个要素是ABC基类和@abstractmethod装饰器。
最简单的一个抽象类例子如下:所有继承ABC的子类,只要包含@abstractmethod装饰的方法,就必须在子类中实现这些方法,否则子类仍然无法实例化。
- from abc import ABC, abstractmethod
- class Animal(ABC):
- @abstractmethod
- def speak(self):
- """子类必须实现这个方法"""
- pass
- # animal = Animal() # TypeError: 不能实例化抽象类
- class Dog(Animal):
- def speak(self):
- print("Woof!")
- dog = Dog()
- dog.speak() # Woof!
复制代码
实际开发中,抽象类往往不止一个抽象方法。来看一个更完整的几何图形示例,它同时定义了area和perimeter两个抽象方法,并且提供了一个普通方法describe给子类直接复用。
- from abc import ABC, abstractmethod
- class Shape(ABC):
- @abstractmethod
- def area(self):
- """计算面积"""
- pass
- @abstractmethod
- def perimeter(self):
- """计算周长"""
- pass
- def describe(self):
- """普通方法,子类可直接使用"""
- print(f"这是一个图形,面积: {self.area()}, 周长: {self.perimeter()}")
复制代码
这里有几个要点需要记住:
1. 继承ABC的类就是抽象类。
2. 被@abstractmethod标记的方法是抽象方法,子类必须实现。
3. 抽象类中可以同时包含普通方法,这些方法提供默认实现,子类可以直接继承使用。
4. 抽象类本身不能创建实例。
除了方法,抽象属性同样可以被强制要求。比如员工类中,可以要求所有子类必须提供一个salary属性,并且该属性以属性的方式访问,而不是方法调用。
- from abc import ABC, abstractmethod
- class Employee(ABC):
- @property
- @abstractmethod
- def salary(self):
- """子类必须实现 salary 属性"""
- pass
- class FullTimeEmployee(Employee):
- def __init__(self, monthly_salary):
- self._monthly_salary = monthly_salary
- @property
- def salary(self):
- return self._monthly_salary
- emp = FullTimeEmployee(10000)
- print(emp.salary) # 10000
复制代码
抽象属性实现时有两个关键点:@abstractmethod负责声明“这是子类必须实现的抽象成员”;@property保证子类实现后可以通过emp.salary这样的属性访问方式取值。装饰器顺序不能写反,@property必须在@abstractmethod的上面,否则会报错。
如果子类只实现了部分抽象方法,那么这个子类本身仍然是一个抽象类,依然不能实例化。例如Rectangle类继承了Shape,实现了area,但没有实现perimeter:
- class Rectangle(Shape):
- def __init__(self, width, height):
- self.width = width
- self.height = height
- def area(self):
- return self.width * self.height
- # 忘记实现 perimeter 方法
- # rect = Rectangle(3, 4) # TypeError: 不能实例化抽象类 Rectangle
复制代码
这种设计在大型项目中特别有用:抽象类相当于一份“接口契约”,强制所有子类按照统一的结构实现关键行为,避免因为遗漏方法而在运行时才暴露问题。配合Python的abc模块,可以在类创建阶段就拦截错误,让代码结构更清晰、更安全。 |