继承与多态

2 阅读5分钟

引言

继承和多态是面向对象编程的两大核心支柱。继承让我们能够复用代码,多态让我们能够编写更灵活的程序。今天我们将深入理解这两个概念,并通过实际案例掌握它们的用法。

一、继承基础

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