多态是面向对象编程的三大特性之一,指同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。
一、多态的基本概念
1. 什么是多态?
# 多态的核心思想:不同对象对同一消息做出不同响应class Animal: def speak(self): return "动物发出声音"class Dog(Animal): def speak(self): # 方法重写 return "汪汪!"class Cat(Animal): def speak(self): # 方法重写 return "喵喵!"class Duck(Animal): def speak(self): # 方法重写 return "嘎嘎!"# 使用多态def animal_speak(animal): """同一个函数处理不同类型的动物""" return animal.speak()# 创建不同动物的实例animals = [Dog(), Cat(), Duck(), Animal()]print("多态演示:")print("-" * 40)for animal in animals: # 调用相同的方法,得到不同的结果 sound = animal_speak(animal) print(f"{animal.__class__.__name__}: {sound}")# 输出:# Dog: 汪汪!# Cat: 喵喵!# Duck: 嘎嘎!# Animal: 动物发出声音
2. 多态与继承的关系
# 多态通常基于继承,但不限于继承class Shape: """形状基类""" def area(self): raise NotImplementedError("子类必须实现area方法")class Rectangle(Shape): """矩形""" def __init__(self, width, height): self.width = width self.height = height def area(self): return self.width * self.height def __str__(self): return f"矩形({self.width}x{self.height})"class Circle(Shape): """圆形""" def __init__(self, radius): self.radius = radius def area(self): import math return math.pi * self.radius ** 2 def __str__(self): return f"圆形(半径{self.radius})"class Triangle(Shape): """三角形""" def __init__(self, base, height): self.base = base self.height = height def area(self): return 0.5 * self.base * self.height def __str__(self): return f"三角形(底{self.base},高{self.height})"# 多态函数:处理任何形状def calculate_total_area(shapes): """计算多个形状的总面积""" total = 0 for shape in shapes: area = shape.area() # 多态调用 total += area print(f"{shape} 的面积: {area:.2f}") return total# 使用print("\n多态计算面积:")print("-" * 40)shapes = [ Rectangle(5, 3), Circle(4), Triangle(6, 4)]total_area = calculate_total_area(shapes)print(f"\n所有形状的总面积: {total_area:.2f}")
二、多态的几种实现方式
1. 继承多态(最常见)
class PaymentMethod: """支付方式基类""" def process_payment(self, amount): raise NotImplementedErrorclass CreditCard(PaymentMethod): def __init__(self, card_number, expiry_date): self.card_number = card_number self.expiry_date = expiry_date def process_payment(self, amount): print(f"验证信用卡 {self.card_number[-4:]}...") print(f"授权金额 ¥{amount:.2f}...") return f"信用卡支付成功: ¥{amount:.2f}"class PayPal(PaymentMethod): def __init__(self, email): self.email = email def process_payment(self, amount): print(f"重定向到PayPal...") print(f"用户 {self.email} 授权支付...") return f"PayPal支付成功: ¥{amount:.2f}"class WeChatPay(PaymentMethod): def process_payment(self, amount): print("生成微信支付二维码...") print("等待用户扫码支付...") return f"微信支付成功: ¥{amount:.2f}"# 支付处理器(多态核心)class PaymentProcessor: def __init__(self): self.payments = [] def add_payment(self, payment_method, amount): """添加支付任务""" self.payments.append((payment_method, amount)) def process_all(self): """处理所有支付(多态调用)""" results = [] for payment_method, amount in self.payments: print(f"\n处理支付: {payment_method.__class__.__name__}") result = payment_method.process_payment(amount) # 多态 results.append(result) return results# 使用print("支付系统多态演示:")print("=" * 50)processor = PaymentProcessor()# 添加不同类型的支付processor.add_payment(CreditCard("1234-5678-9012-3456", "12/25"), 199.99)processor.add_payment(PayPal("user@example.com"), 299.99)processor.add_payment(WeChatPay(), 99.99)# 统一处理results = processor.process_all()print("\n支付结果:")for result in results: print(f" ✓ {result}")
2. 鸭子类型多态(Python特色)
"""鸭子类型(Duck Typing):"如果它走起来像鸭子,叫起来像鸭子,那么它就是鸭子"Python不关心对象的类型,只关心对象是否有需要的方法"""class FileReader: """文件读取器""" def read(self, filename): with open(filename, 'r', encoding='utf-8') as f: return f.read()class StringReader: """字符串读取器""" def __init__(self, content): self.content = content def read(self, filename=None): return self.contentclass NetworkReader: """网络读取器""" def read(self, url): import urllib.request with urllib.request.urlopen(url) as response: return response.read().decode('utf-8')# 多态函数:不关心具体类型,只关心是否有read方法def process_data(reader, source): """处理数据源(鸭子类型多态)""" try: data = reader.read(source) # 处理数据... lines = data.strip().split('\n') return { 'source': source, 'length': len(data), 'lines': len(lines), 'content_preview': data[:50] + '...' if len(data) > 50 else data } except Exception as e: return {'error': str(e), 'source': source}print("鸭子类型多态演示:")print("=" * 50)# 创建不同的读取器(没有共同基类)readers = [ ("文件读取器", FileReader(), "example.txt"), ("字符串读取器", StringReader("第一行\n第二行\n第三行"), None), ("网络读取器", NetworkReader(), "http://example.com"),]# 统一处理(多态)for name, reader, source in readers: print(f"\n使用 {name}:") result = process_data(reader, source) if 'error' in result: print(f" 错误: {result['error']}") else: print(f" 源: {result['source']}") print(f" 长度: {result['length']} 字符") print(f" 行数: {result['lines']}") print(f" 预览: {result['content_preview']}")# 验证鸭子类型print("\n鸭子类型验证:")obj1 = FileReader()obj2 = StringReader("test")obj3 = "这不是读取器"print(f"FileReader有read方法吗? {hasattr(obj1, 'read')}")print(f"StringReader有read方法吗? {hasattr(obj2, 'read')}")print(f"字符串有read方法吗? {hasattr(obj3, 'read')}")
3. 抽象基类多态
from abc import ABC, abstractmethodclass DatabaseConnection(ABC): """数据库连接抽象基类""" @abstractmethod def connect(self): """连接数据库""" pass @abstractmethod def execute_query(self, sql): """执行查询""" pass @abstractmethod def close(self): """关闭连接""" pass # 模板方法 def execute_transaction(self, queries): """执行事务(模板方法模式)""" self.connect() try: results = [] for sql in queries: result = self.execute_query(sql) # 多态调用 results.append(result) return results finally: self.close()class MySQLConnection(DatabaseConnection): """MySQL数据库连接""" def connect(self): print("连接到MySQL数据库...") return "mysql_connection" def execute_query(self, sql): print(f"MySQL执行: {sql}") return {"query": sql, "rows_affected": 1} def close(self): print("关闭MySQL连接")class PostgreSQLConnection(DatabaseConnection): """PostgreSQL数据库连接""" def connect(self): print("连接到PostgreSQL数据库...") return "postgresql_connection" def execute_query(self, sql): print(f"PostgreSQL执行: {sql}") return {"query": sql, "rows": [{"id": 1, "name": "test"}]} def close(self): print("关闭PostgreSQL连接")class SQLiteConnection(DatabaseConnection): """SQLite数据库连接""" def connect(self): print("连接到SQLite数据库...") return "sqlite_connection" def execute_query(self, sql): print(f"SQLite执行: {sql}") return {"query": sql, "success": True} def close(self): print("关闭SQLite连接")# 数据库管理器(使用多态)class DatabaseManager: def __init__(self): self.connections = {} def add_connection(self, name, connection): """添加数据库连接""" if not isinstance(connection, DatabaseConnection): raise TypeError("必须是DatabaseConnection类型") self.connections[name] = connection def execute_on_all(self, sql): """在所有数据库上执行SQL(多态)""" results = {} for name, connection in self.connections.items(): print(f"\n在 {name} 上执行:") result = connection.execute_transaction([sql]) results[name] = result return resultsprint("抽象基类多态演示:")print("=" * 50)# 创建管理器manager = DatabaseManager()# 添加不同类型的数据库连接manager.add_connection("MySQL", MySQLConnection())manager.add_connection("PostgreSQL", PostgreSQLConnection())manager.add_connection("SQLite", SQLiteConnection())# 在多态执行sql = "SELECT * FROM users"results = manager.execute_on_all(sql)print("\n执行结果:")for db_name, result in results.items(): print(f" {db_name}: {result}")
总结
多态的核心要点:
多态的实现方式:
方法重写:子类重写父类方法
抽象基类:使用abc模块定义接口
鸭子类型:只关心对象有什么方法
适用场景:
✅ 需要处理多种类型的相似操作
✅ 系统需要支持扩展和插件
✅ 代码需要提高复用性和灵活性
✅ 实现回调机制和事件处理
Python多态的特色:
鸭子类型是Python的特色
不需要显式接口声明
动态类型系统天然支持多态
结合装饰器、元类等特性更强大