第63集:抽象类与接口
学习目标
- 理解抽象类的概念与作用
- 掌握 Python 中
abc模块的使用方法 - 学会定义抽象方法和抽象属性
- 理解接口的概念及其在 Python 中的实现方式
- 能够使用抽象类设计稳定的类层次结构
1. 什么是抽象类
抽象类是一种不能被实例化的类,它的主要目的是为子类提供一个通用的模板,强制子类实现某些方法。
在 Python 中,我们通过 abc(Abstract Base Classes)模块来实现抽象类。
1.1 为什么需要抽象类
- 定义规范:规定子类必须实现的方法,避免遗漏关键功能
- 提高可维护性:接口统一,便于多人协作
- 防止误用:抽象类不能直接创建对象,减少错误使用
2. abc 模块基础
Python 的 abc 模块提供了 ABC 类和 abstractmethod 装饰器来定义抽象类和方法。
2.1 基本语法
from abc import ABC, abstractmethod
class 抽象类名(ABC):
@abstractmethod
def 方法名(self):
pass2.2 简单示例
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def speak(self):
pass
class Dog(Animal):
def speak(self):
return "汪汪!"
class Cat(Animal):
def speak(self):
return "喵喵!"
# animal = Animal() # ❌ TypeError: Can't instantiate abstract class
dog = Dog()
cat = Cat()
print(dog.speak()) # 汪汪!
print(cat.speak()) # 喵喵!3. 抽象方法
抽象方法是在抽象类中声明但不实现的方法,子类必须重写它,否则子类也是抽象类。
3.1 多抽象方法示例
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
pass
@abstractmethod
def perimeter(self):
pass
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)
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14159 * self.radius ** 2
def perimeter(self):
return 2 * 3.14159 * self.radius
# shape = Shape() # ❌ 无法实例化
rect = Rectangle(3, 4)
circ = Circle(5)
print(f"矩形面积: {rect.area()}, 周长: {rect.perimeter()}")
print(f"圆面积: {circ.area():.2f}, 周长: {circ.perimeter():.2f}")4. 抽象属性
除了抽象方法,abc 还支持抽象属性,需要使用 @property 和 @abstractmethod 组合。
4.1 抽象属性示例
from abc import ABC, abstractmethod
class Vehicle(ABC):
@property
@abstractmethod
def speed(self):
pass
@abstractmethod
def move(self):
pass
class Car(Vehicle):
def __init__(self, speed):
self._speed = speed
@property
def speed(self):
return self._speed
def move(self):
return f"汽车以 {self._speed} km/h 行驶"
class Bicycle(Vehicle):
def __init__(self, speed):
self._speed = speed
@property
def speed(self):
return self._speed
def move(self):
return f"自行车以 {self._speed} km/h 骑行"
car = Car(100)
bike = Bicycle(20)
print(car.move())
print(bike.move())5. 接口的概念与实现
接口是一组方法签名的集合,规定了类应该具备的行为。Python 没有专门的 interface 关键字,但可以用抽象类模拟接口。
5.1 多接口示例
from abc import ABC, abstractmethod
class Flyable(ABC):
@abstractmethod
def fly(self):
pass
class Swimmable(ABC):
@abstractmethod
def swim(self):
pass
class Duck(Flyable, Swimmable):
def fly(self):
return "鸭子飞起来了"
def swim(self):
return "鸭子在水里游泳"
duck = Duck()
print(duck.fly())
print(duck.swim())6. 实际应用案例:支付系统
假设我们要设计一个支持多种支付方式的系统:
from abc import ABC, abstractmethod
class Payment(ABC):
@abstractmethod
def pay(self, amount):
pass
@abstractmethod
def refund(self, amount):
pass
class Alipay(Payment):
def pay(self, amount):
return f"支付宝支付 {amount} 元"
def refund(self, amount):
return f"支付宝退款 {amount} 元"
class WechatPay(Payment):
def pay(self, amount):
return f"微信支付 {amount} 元"
def refund(self, amount):
return f"微信退款 {amount} 元"
def process_payment(payment: Payment, amount):
print(payment.pay(amount))
alipay = Alipay()
wechat = WechatPay()
process_payment(alipay, 100)
process_payment(wechat, 200)7. 常见错误与注意事项
- 抽象类不能直接实例化
- 子类必须实现所有抽象方法,否则仍是抽象类
- 抽象属性需用
@property+@abstractmethod - 接口可通过多重继承实现
- 抽象类可以有普通方法(非抽象),子类可直接继承使用
8. 课后练习
- 设计一个
Database抽象类,要求实现connect、query、close三个抽象方法,并用不同的子类实现 MySQL 和 SQLite 的具体逻辑。 - 定义一个
Logger接口(抽象类),包含log(message)抽象方法,并实现文件日志和控制台日志两个子类。 - 结合属性装饰器,为抽象类添加抽象属性如
version,并在子类中实现。
总结
- 抽象类:用
ABC和abstractmethod定义,不能实例化,用于约束子类实现关键方法。 - 接口:在 Python 中用多重抽象类实现,定义行为规范。
- 抽象类和接口提高了代码的规范性、可扩展性和可维护性,是大型项目设计的重要工具。
下一集我们将进入 魔术方法基础,探索 Python 的特殊方法如何让对象表现得更像内置类型!