类的组合(对比继承)
类的组合(Composition)详解
类的组合是面向对象编程中 “has-a”关系 的实现方式,指一个类将其他类的实例作为自己的属性,通过组合多个对象的功能来构建复杂系统。与继承不同,组合强调 对象之间的协作 而非层级关系。
一、基本概念
1. 组合 vs 继承
特性 | 组合(Composition) | 继承(Inheritance) |
---|---|---|
关系类型 | “has-a”(有一个) | “is-a”(是一个) |
灵活性 | 高(动态替换部分对象) | 低(父类改变可能影响子类) |
代码复用 | 通过包含其他对象实现 | 通过继承父类实现 |
典型场景 | 汽车包含发动机、轮胎 | 狗是动物的一种 |
2. 核心思想
- 将功能委托给其他对象,而非通过继承获得。
- 通过属性引用其他类,实现模块化设计。
二、基本语法
class Engine:def start(self):print("引擎启动")class Car:def __init__(self):self.engine = Engine() # 组合:Car 包含一个 Enginedef run(self):self.engine.start() # 调用组合对象的方法print("汽车行驶")car = Car()
car.run()
输出:
引擎启动
汽车行驶
三、组合的优势
1. 灵活替换部件
组合允许运行时动态更换对象:
class ElectricEngine:def start(self):print("电动机启动")car.engine = ElectricEngine() # 更换引擎
car.run()
输出:
电动机启动
汽车行驶
2. 避免继承的复杂性
多重继承易导致混乱,组合更清晰:
class Tire:def rotate(self):print("轮胎滚动")class Car:def __init__(self):self.engine = Engine()self.tires = [Tire() for _ in range(4)] # 组合多个对象def run(self):self.engine.start()for tire in self.tires:tire.rotate()
3. 更符合现实逻辑
例如:电脑由CPU、内存等组件构成,而非通过继承实现:
class CPU:def compute(self):print("计算数据")class Computer:def __init__(self):self.cpu = CPU()def work(self):self.cpu.compute()
四、组合的常见模式
1. 直接组合
将对象作为属性直接嵌入:
class Author:def __init__(self, name):self.name = nameclass Book:def __init__(self, title, author_name):self.title = titleself.author = Author(author_name) # 组合 Author 对象
2. 通过参数注入
依赖外部传入的对象(提高灵活性):
class Logger:def log(self, message):print(message)class App:def __init__(self, logger): # 注入 Logger 对象self.logger = loggerdef run(self):self.logger.log("程序启动")app = App(Logger())
app.run()
3. 组合多个对象
一个类可组合多个不同类的实例:
class Classroom:def __init__(self):self.students = [] # 组合多个 Student 对象self.teacher = None # 组合一个 Teacher 对象
五、组合 vs 继承的选择
何时用组合?
- 需要动态增减功能时(如插件系统)。
- 不同对象生命周期独立(如汽车和引擎)。
- 避免多重继承的复杂性。
何时用继承?
- 需要表达“是一种”关系时(如
Dog
是Animal
)。 - 子类必须完全继承父类行为且无需替换部分功能。
六、实际应用案例
1. 游戏开发
class Weapon:def attack(self):passclass Sword(Weapon):def attack(self):print("挥剑攻击")class Player:def __init__(self):self.weapon = None # 可动态更换武器def equip(self, weapon):self.weapon = weapondef fight(self):if self.weapon:self.weapon.attack()player = Player()
player.equip(Sword())
player.fight() # 输出: 挥剑攻击
2. 设计模式中的组合
- 策略模式:通过组合不同算法对象动态改变行为。
- 装饰器模式:通过组合嵌套对象扩展功能。
七、总结
关键点 | 说明 |
---|---|
本质 | 通过对象引用实现功能协作(“has-a”关系) |
语法 | 将其他类的实例作为属性 |
优势 | 灵活性高、避免继承深度问题、符合模块化设计 |
典型场景 | 系统由多个独立部件组成(如电脑硬件、游戏角色装备) |
与继承对比 | 优先使用组合,除非必须用继承表达“is-a”关系 |
核心原则:
“组合优于继承”(Composition over Inheritance),这是现代面向对象设计的重要准则。