第 2 篇 · 功法:面向对象(下)· 继承衣钵,多态江湖
师门传承是为继承,一招百式是为多态。
下篇传授「继承」与「多态」的武林绝学,让你站在巨人的肩膀上,一招鲜吃遍天。

1. 继承
1.1 什么是继承
子类自动继承父类所有的属性和方法。
继承链示例
plain
Animal(动物基类)
├── IsLandAnimal(陆地生物)
│ └── CatAnimal(猫科动物)
│ ├── Tiger(老虎)
│ └── Cat(猫)
├── OceanAnimal(海洋生物)
└── AirAnimal(空中生物)
python
# 基类
class Animal:
def __init__(self, name="基础动物类"):
self.name = name
# 单继承
class IsLandAnimal(Animal):
pass
# 多级继承
class CatAnimal(IsLandAnimal):
pass
class Tiger(CatAnimal):
pass
print(Tiger().name) # 输出: 基础动物类
1.2 方法重写
子类定义和父类同名的方法,即覆盖父类方法。
python
class Animal:
def call(self):
print("动物在叫")
class Cat(Animal):
def call(self): # 重写父类方法
print("喵喵喵")
c = Cat()
c.call() # 喵喵喵(优先找子类,找不到再找父类)
1.3 方法执行顺序
子类 → 父类 → 父类的父类 → ... → object → 报错
python
class Cat(Animal):
def call(self):
print("喵喵喵")
c = Cat()
c.call() # 子类有 → 执行子类
c.sleep() # 子类没有 → 找父类
c.test() # 父类也没有 → 找 object → 还没有 → 报错
1.4 子类调用父类方法(三种方式)
python
class Car:
def run(self):
print("汽车在跑")
class HyBirdCar(Car):
def run(self):
# 方式1:super().方法名()
super().run()
# 方式2:super(当前类名, self).方法名()
super(HyBirdCar, self).run()
# 方式3:父类名.方法名(self)
Car.run(self)
1.5 子类构造调用父类构造
python
class Car:
def __init__(self, car_name, car_color):
self.car_name = car_name
self.car_color = car_color
class HyBirdCar(Car):
def __init__(self, car_name, car_color, car_type):
# 公共属性走父类构造
super().__init__(car_name, car_color)
# 扩展属性自己写
self.car_type = car_type
2. 多继承
2.1 基本语法
python
class Child(Father, Monther): # 多继承
pass
2.2 方法冲突
如果多个父类有同名方法 ,按继承顺序(从左到右)优先调用第一个匹配的。
python
class Father:
def work(self):
print("爸爸工作")
class Monther:
def work(self):
print("妈妈工作")
class Child(Father, Monther):
def work(self):
Monther.work(self) # 可以指定调用哪个父类的方法
c = Child()
c.work() # 如果子类没有 work,会调用 Father.work()
2.3 MRO(方法解析顺序)
使用 类名.__mro__ 或 类名.mro() 查看执行顺序。
python
class A: pass
class B(A): pass
class C(A): pass
class D(B, C): pass
print(D.__mro__) # (<class 'D'>, <class 'B'>, <class 'C'>, <class 'A'>, <class 'object'>)
print(D.mro()) # 同上
super()严格遵循 MRO 顺序去查找方法。
3. 多态
3.1 什么是多态
同一个方法名,传入不同的对象,表现出不同的行为。
3.2 多态的条件
- 有继承
- 有方法重写
- 父类引用指向子类对象
3.3 多态示例
python
class PayBase:
def pay(self):
print("基础支付")
class WeChat(PayBase):
def pay(self):
print("微信支付")
class AliPay(PayBase):
def pay(self):
print("支付宝支付")
def pay_way(obj):
if isinstance(obj, PayBase): # 类型检查
obj.pay()
pay_way(WeChat()) # 微信支付
pay_way(AliPay()) # 支付宝支付
4. 类属性、类方法、静态方法
4.1 类属性
类和所有实例共享 的属性,适合做统计汇总。
python
class Tool:
tool_count = 0 # 类属性
def __init__(self, tool_name):
self.tool_name = tool_name
Tool.tool_count += 1 # 每创建一个实例,计数+1
t1 = Tool("斧子")
t2 = Tool("锤子")
print(Tool.tool_count) # 输出: 2(推荐用类名调用)
print(t1.tool_count) # 输出: 2(实例也可以调用)
| 调用方式 | 说明 |
|---|---|
Tool.tool_count |
✅ 推荐 |
t1.tool_count |
⚠️ 可以,但不推荐(容易和实例属性混淆) |
4.2 类方法
使用 @classmethod 装饰,第一个参数是 cls(类本身),可访问类属性。
python
class Tool:
tool_count = 0
@classmethod
def show_tool_count(cls):
print(f"当前创建了 {cls.tool_count} 个工具")
Tool.show_tool_count() # 调用类方法
4.3 静态方法
使用 @staticmethod 装饰,不需要 self 或 cls 参数,相当于普通函数,但属于类的命名空间。
python
class Tool:
@staticmethod
def show_help_info():
print("这是工具类的帮助信息")
Tool.show_help_info() # 调用静态方法
5. 游戏小案例(综合实战)
需求:设计一个 Game 类
| 类型 | 名称 | 说明 |
|---|---|---|
| 类属性 | top_score |
记录历史总积分 |
| 实例属性 | player_name |
记录当前玩家姓名 |
| 静态方法 | show_help() |
显示游戏帮助信息 |
| 类方法 | show_all_score() |
显示历史总积分 |
| 实例方法 | start_game() |
开始当前玩家的游戏 |
python
import random
class Game:
top_score = 0 # 类属性
def __init__(self, player_name):
self.player_name = player_name
@staticmethod
def show_help():
print("游戏帮助信息")
@classmethod
def show_all_score(cls):
print(f"历史总积分:{cls.top_score}")
def start_game(self):
print(f"{self.player_name} 开始玩游戏")
score = random.randint(100, 200)
Game.top_score += score
print(f"本轮得分:{score}")
g1 = Game("张三")
g1.start_game()
g2 = Game("李四")
g2.start_game()
Game.show_all_score() # 累加了两轮得分
6. 快速记忆表(下篇)
| 概念 | 关键词 | 说明 |
|---|---|---|
| 继承 | class 子类(父类) |
复用父类属性和方法 |
| 重写 | 同名方法 | 覆盖父类方法 |
super() |
调用父类方法 | 避免硬编码父类名 |
| MRO | __mro__ |
方法解析顺序 |
| 多继承 | class A(B, C) |
继承多个父类 |
| 多态 | 同一个方法不同行为 | 继承 + 重写 |
| 类属性 | 类名.属性 | 所有实例共享 |
| 类方法 | @classmethod |
操作类属性 |
| 静态方法 | @staticmethod |
普通函数,归类管理 |