Skip to content

3.2 继承与多态

引言

小白理解 - 继承是什么?

想象动物世界

动物(Animal)        ← 父类/基类
 ├── 狗(Dog)        ← 子类,继承自动物
 ├── 猫(Cat)        ← 子类,继承自动物
 └── 鸟(Bird)       ← 子类,继承自动物

继承的好处

  • 所有动物都能"吃"(eat)、"睡"(sleep)—— 写一次,大家都有
  • 狗可以额外"叫"(bark)—— 子类可以有自己的特殊功能
  • 猫的"叫"是"喵喵",狗的"叫"是"汪汪"—— 同一个动作,不同表现(多态)

一句话:继承 = 子类复用父类的功能,还能加自己的特色

小白理解 - 多态是什么?

多态 = 同一个动作,不同的表现

python
# 所有动物都能"叫",但叫法不同
狗.叫()  # → "汪汪!"
猫.叫()  # → "喵喵~"
鸟.叫()  # → "叽叽!"

# 你不用管它是什么动物,调用 .叫() 就行
for 动物 in [狗, 猫, 鸟]:
    动物.叫()  # 自动调用各自的叫法

继承基础

小白理解 - 看懂继承代码

python
class BaseAgent:           # ← 父类(基类)
    def execute(self, task):
        return "基础执行"

class SearchAgent(BaseAgent):  # ← 子类,括号里写父类名
    def execute(self, task):   # ← 重写父类方法
        return "搜索执行"      # ← 子类的专属实现

关键点

  • class 子类(父类): —— 括号里写父类名就是继承
  • 子类自动拥有父类的所有方法和属性
  • 子类可以"重写"父类方法,实现自己的版本
python
class BaseAgent:
    """基础 Agent 类"""

    def __init__(self, name: str):
        self.name = name

    def execute(self, task: str) -> str:
        """执行任务(子类重写)"""
        return f"{self.name} 执行: {task}"

class SearchAgent(BaseAgent):
    """搜索 Agent"""

    def execute(self, task: str) -> str:
        """重写执行方法"""
        return f"[搜索] {self.name}: 搜索 '{task}'"

class AnalysisAgent(BaseAgent):
    """分析 Agent"""

    def execute(self, task: str) -> str:
        return f"[分析] {self.name}: 分析 '{task}'"

# 多态:同一接口,不同实现
agents = [
    SearchAgent("搜索助手"),
    AnalysisAgent("分析助手")
]

for agent in agents:
    print(agent.execute("Python 教程"))

运行结果解读

[搜索] 搜索助手: 搜索 'Python 教程'
[分析] 分析助手: 分析 'Python 教程'

这就是多态

  • 两个 Agent 都调用 .execute()
  • 但搜索助手执行"搜索",分析助手执行"分析"
  • 调用方不需要知道具体是什么类型的 Agent

实战:Agent 层次结构

小白理解 - ABC 和 abstractmethod

ABC(抽象基类) = 只能被继承,不能直接使用的"模板类"

类比:驾照考试大纲

  • 大纲规定:必须会"侧方停车"、"倒车入库"
  • 但大纲本身不能开车,只是规定要求
  • 学员(子类)必须学会这些技能,才能拿到驾照
python
from abc import ABC, abstractmethod

class Agent(ABC):              # ← ABC = 抽象基类
    @abstractmethod            # ← 标记为"必须实现"
    def process(self, input):  # ← 子类必须写这个方法
        pass

# 错误示范:
agent = Agent()  # ❌ 报错!抽象类不能实例化

# 正确做法:
class MyAgent(Agent):
    def process(self, input):  # ✅ 子类实现了这个方法
        return "处理结果"

agent = MyAgent()  # ✅ 可以创建

小白理解 - super() 是什么?

super() = 调用父类的方法

python
class LLMAgent(Agent):
    def __init__(self, name, model):
        super().__init__(name)  # ← 先让父类完成初始化
        self.model = model      # ← 再添加子类特有的属性

类比:你继承了爸爸的房子(super().__init__()),然后自己装修添家具(self.model

python
from abc import ABC, abstractmethod
from typing import List

class Agent(ABC):
    """抽象 Agent 基类"""

    def __init__(self, name: str):
        self.name = name
        self.history: List[str] = []

    @abstractmethod
    def process(self, input: str) -> str:
        """处理输入(子类必须实现)"""
        pass

    def log(self, message: str) -> None:
        """记录日志"""
        self.history.append(f"[{self.name}] {message}")

class LLMAgent(Agent):
    """LLM Agent"""

    def __init__(self, name: str, model: str):
        super().__init__(name)
        self.model = model

    def process(self, input: str) -> str:
        self.log(f"使用 {self.model} 处理")
        return f"LLM 响应: {input}"

class ToolAgent(Agent):
    """工具 Agent"""

    def __init__(self, name: str, tools: List[str]):
        super().__init__(name)
        self.tools = tools

    def process(self, input: str) -> str:
        self.log(f"使用工具: {self.tools}")
        return f"工具执行结果"

# 使用
llm_agent = LLMAgent("GPT助手", "gpt-4")
tool_agent = ToolAgent("工具助手", ["search", "calc"])

print(llm_agent.process("你好"))
print(tool_agent.process("搜索"))

代码结构图解

Agent(抽象基类)

 ├── name        ← 所有Agent都有名字
 ├── history     ← 所有Agent都有历史记录
 ├── log()       ← 所有Agent都能记日志
 └── process()   ← 抽象方法,子类必须实现

      ├── LLMAgent.process()   → 调用 LLM 处理
      └── ToolAgent.process()  → 调用工具处理

本节小结

概念一句话解释记忆口诀
继承子类复用父类的功能继承 = 遗产
多态同一接口,不同实现多态 = 变形
重写子类替换父类的方法重写 = 改造
super()调用父类的方法super = 爸爸
ABC只能继承不能实例化的类ABC = 模板
@abstractmethod标记子类必须实现的方法abstract = 必做题

下一节:3.3 Protocol 与 ABC

基于 MIT 许可证发布。内容版权归作者所有。