引言
继承和多态是面向对象编程的两大核心支柱。继承让我们能够复用代码,多态让我们能够编写更灵活的程序。今天我们将深入理解这两个概念,并通过实际案例掌握它们的用法。
一、继承基础
1.1 什么是继承
继承允许一个类(子类)继承另一个类(父类)的属性和方法,实现代码复用。
# 父类:动物
class Animal:
def __init__(self, name, age):
self.name = name
self.age = age
def speak(self):
return "一些声音"
def info(self):
return f"{self.name},{self.age}岁"
# 子类:狗
class Dog(Animal):
def __init__(self, name, age, breed):
super().__init__(name, age) # 调用父类构造函数
self.breed = breed
def speak(self): # 方法重写
return "汪汪汪!"
def fetch(self): # 子类扩展方法
return f"{self.name} 去捡球了"
# 使用示例
dog = Dog("小白", 3, "金毛")
print(dog.info()) # 小白,3 岁(继承的方法)
print(dog.speak()) # 汪汪汪!(重写的方法)
print(dog.fetch()) # 小白 去捡球了(扩展的方法)
1.2 super() 的正确使用
super() 用于调用父类的方法,在方法重写时尤其重要。
class Cat(Animal):
def __init__(self, name, age, color):
super().__init__(name, age)
self.color = color
def speak(self):
# 保留父类行为并扩展
base_sound = super().speak()
return f"{base_sound} → 喵喵喵!"
def info(self):
# 扩展父类方法
base_info = super().info()
return f"{base_info},{self.color}色"
cat = Cat("咪咪", 2, "白")
print(cat.info()) # 咪咪,2 岁,白色
print(cat.speak()) # 一些声音 → 喵喵喵!
二、多态的魅力
2.1 什么是多态
多态允许不同类的对象对同一消息做出不同响应。同一接口,多种实现。
# 动物音乐会
class Dog(Animal):
def speak(self):
return "汪汪汪!"
class Cat(Animal):
def speak(self):
return "喵喵喵!"
class Duck(Animal):
def speak(self):
return "嘎嘎嘎!"
# 多态演示
def animal_concert(animals):
"""动物音乐会 - 同一接口,不同表现"""
for animal in animals:
print(f"{animal.info()} 说:{animal.speak()}")
# 创建动物列表
animals = [
Dog("小白", 3, "金毛"),
Cat("咪咪", 2, "白"),
Duck("大黄", 1, "绿头")
]
# 演奏开始
animal_concert(animals)
输出:
小白,3 岁 说:汪汪汪!
咪咪,2 岁 说:喵喵喵!
大黄,1 岁 说:嘎嘎嘎!
2.2 多态的优势
# 不使用多态的代码
def make_dog_sound(dog):
return dog.speak()
def make_cat_sound(cat):
return cat.speak()
# 使用多态的代码
def make_sound(animal):
return animal.speak() # 一个函数处理所有动物
# 新增动物类型时,无需修改 make_sound 函数
class Bird(Animal):
def speak(self):
return "叽叽喳喳!"
bird = Bird("小鸟", 1)
print(make_sound(bird)) # 直接可用
三、多重继承
3.1 多重继承基础
Python 支持一个类继承多个父类。
class Flyable:
def fly(self):
return "正在飞翔"
class Swimmable:
def swim(self):
return "正在游泳"
class Duck(Flyable, Swimmable):
def __init__(self, name):
self.name = name
def info(self):
return f"{self.name} 会飞也会游泳"
duck = Duck("唐老鸭")
print(duck.info()) # 唐老鸭 会飞也会游泳
print(duck.fly()) # 正在飞翔
print(duck.swim()) # 正在游泳
3.2 MRO(方法解析顺序)
多重继承时,Python 使用 C3 线性化算法确定方法调用顺序。
class A:
def do_something(self):
print("A")
class B(A):
def do_something(self):
print("B")
super().do_something()
class C(A):
def do_something(self):
print("C")
super().do_something()
class D(B, C):
def do_something(self):
print("D")
super().do_something()
d = D()
d.do_something()
# 查看 MRO
print(D.__mro__)
# (<class 'D'>, <class 'B'>, <class 'C'>, <class 'A'>, <class 'object'>)
输出:
D
B
C
A
3.3 多重继承注意事项
# ⚠️ 钻石继承问题
class Animal:
def __init__(self, name):
self.name = name
class Flyable(Animal):
def __init__(self, name, wingspan):
super().__init__(name)
self.wingspan = wingspan
class Swimmable(Animal):
def __init__(self, name, max_depth):
super().__init__(name)
self.max_depth = max_depth
# ✅ 正确使用 super() 避免重复初始化
class Duck(Flyable, Swimmable):
def __init__(self, name, wingspan, max_depth):
super().__init__(name, wingspan, max_depth)
duck = Duck("唐老鸭", 1.5, 2.0)
print(duck.name) # 唐老鸭
print(duck.wingspan) # 1.5
print(duck.max_depth) # 2.0
四、实战案例:电商支付系统
4.1 抽象基类定义
from abc import ABC, abstractmethod
class Payment(ABC):
"""支付抽象基类"""
@abstractmethod
def pay(self, amount):
"""抽象方法:执行支付"""
pass
@abstractmethod
def refund(self, transaction_id):
"""抽象方法:执行退款"""
pass
def log_transaction(self, action, amount):
"""具体方法:记录交易日志"""
print(f"[日志] {action}: ¥{amount:.2f}")
4.2 多种支付方式实现
class Alipay(Payment):
"""支付宝支付"""
def pay(self, amount):
self.log_transaction("支付宝支付", amount)
print(f"✓ 支付宝支付成功:¥{amount:.2f}")
return True
def refund(self, transaction_id):
self.log_transaction("支付宝退款", 0)
print(f"✓ 支付宝退款成功:订单 {transaction_id}")
return True
class WeChatPay(Payment):
"""微信支付"""
def pay(self, amount):
self.log_transaction("微信支付", amount)
print(f"✓ 微信支付成功:¥{amount:.2f}")
return True
def refund(self, transaction_id):
self.log_transaction("微信退款", 0)
print(f"✓ 微信退款成功:订单 {transaction_id}")
return True
class CreditCard(Payment):
"""信用卡支付"""
def __init__(self, card_number):
self.card_number = card_number[-4:]
def pay(self, amount):
self.log_transaction(f"信用卡支付 (****{self.card_number})", amount)
print(f"✓ 信用卡支付成功:¥{amount:.2f}")
return True
def refund(self, transaction_id):
self.log_transaction(f"信用卡退款 (****{self.card_number})", 0)
print(f"✓ 信用卡退款成功:订单 {transaction_id}")
return True
4.3 订单系统使用多态
class Order:
"""订单类"""
def __init__(self, order_id, amount):
self.order_id = order_id
self.amount = amount
def checkout(self, payment: Payment):
"""结账 - 接受任何 Payment 子类"""
print(f"\n订单 {self.order_id} 开始结算")
print(f"金额:¥{self.amount:.2f}")
print("-" * 30)
if payment.pay(self.amount):
print(f"订单 {self.order_id} 支付完成")
return True
return False
def return_item(self, payment: Payment):
"""退货 - 同样接受任何 Payment 子类"""
print(f"\n订单 {self.order_id} 开始退货")
if payment.refund(self.order_id):
print(f"订单 {self.order_id} 退货完成")
return True
return False
# 使用示例
order = Order("20260323001", 299.00)
# 可以使用任何支付方式
order.checkout(Alipay())
order.checkout(WeChatPay())
order.checkout(CreditCard("1234567890123456"))
五、最佳实践总结
| 实践 | 说明 | 示例 |
|---|---|---|
| 优先使用组合 | 能用组合就不用继承,降低耦合 | Duck 包含 Wings 而非继承 |
| 遵循 LSP 原则 | 子类应能替换父类而不影响程序 | Dog 可替换 Animal |
| 合理使用 super() | 确保父类方法被正确调用 | super().__init__() |
| 避免深层继承 | 继承层次不超过 3 层 | 过深考虑重构 |
| 明确 MRO 顺序 | 多重继承时查看 __mro__ | Class.__mro__ |
| 使用抽象基类 | 定义清晰接口,强制子类实现 | ABC + @abstractmethod |