人狗大战Ⅰ-2:面向对象关系详解
下面以“人狗大战”为场景,系统梳理面向对象中继承、组合、聚合、关联、依赖5种核心关系,通过战斗细节直观展示每种关系的特性与区别。
场景核心逻辑
- 所有角色(人、狗)都是“生物”,共享生命值、受伤等基础特性(继承);
- 人自带拳头、狗自带牙齿,这些是身体不可分割的部分(组合);
- 人可持有武器、狗可佩戴项圈,这些装备可独立存在并更换(聚合);
- 角色的敌人可以是任何人、狗或其他生物,用列表长期存储(关联);
- 战斗中可临时使用药水疗伤,用完即弃(依赖)。
代码实现与关系解析
1. 继承(Inheritance):“是一种”(is-a)的层级关系
定义:子类是父类的“特殊类型”,继承父类的属性和方法,实现共性复用。
场景:人(Human)和狗(Dog)都是“生物(Creature)”,共享“生命值”“受伤”“存活判断”等基础能力。
class Creature:
"""生物基类(所有角色的父类)"""
def __init__(self, name, hp=100):
self.name = name # 名称
self.hp = hp # 生命值
def take_damage(self, damage):
"""所有生物都会受伤(共性方法)"""
self.hp = max(0, self.hp - damage)
return f"{self.name}受{damage}点伤害,剩余{self.hp}血"
def is_alive(self):
"""所有生物都能判断是否存活(共性方法)"""
return self.hp > 0
# 人类:继承自生物(“人是一种生物”)
class Human(Creature):
def __init__(self, name):
super().__init__(name) # 继承父类的属性初始化
# 狗:继承自生物(“狗是一种生物”)
class Dog(Creature):
def __init__(self, name):
super().__init__(name)
2. 组合(Composition):“不可分离的部分”(整体包含部分,部分依赖整体)
定义:部分是整体“与生俱来”的组成部分,脱离整体后无意义,整体销毁时部分也会销毁。
场景:人的拳头、狗的牙齿是身体的一部分,创建角色时自动生成,无法单独存在或分离。
class Fist:
"""人的拳头(组合:人体不可分割的部分)"""
def hit(self):
return 5 # 拳头攻击力(仅作为人的一部分生效)
class Tooth:
"""狗的牙齿(组合:狗体不可分割的部分)"""
def bite(self):
return 8 # 牙齿伤害(仅作为狗的一部分生效)
# 完善人类:包含拳头(组合关系)
class Human(Creature):
def __init__(self, name):
super().__init__(name)
self.fist = Fist() # 创建人时自动生成拳头(不可分离)
# 完善狗类:包含牙齿(组合关系)
class Dog(Creature):
def __init__(self, name):
super().__init__(name)
self.tooth = Tooth() # 创建狗时自动生成牙齿(不可分离)
3. 聚合(Aggregation):“可分离的部分”(整体包含部分,部分独立存在)
定义:部分是整体“可附加”的组件,可独立存在(如武器可丢在地上),整体和部分的生命周期互不影响。
场景:人持有的武器、狗佩戴的项圈,可单独创建后“附加”到角色上,也可随时分离。
class Weapon:
"""武器(聚合:可被人持有,脱离人仍有意义)"""
def __init__(self, name, damage):
self.name = name # 武器名称(如“长剑”)
self.damage = damage # 攻击力
class Collar:
"""项圈(聚合:可被狗佩戴,取下后仍存在)"""
def __init__(self, material):
self.defense = 2 if material == "金属" else 1 # 防御加成(金属项圈更强)
# 完善人类:支持持有武器(聚合关系)
class Human(Creature):
def __init__(self, name):
super().__init__(name)
self.fist = Fist() # 组合
self.weapon = None # 聚合:初始无武器,可后续添加(如捡起地上的剑)
# 完善狗类:支持佩戴项圈(聚合关系)
class Dog(Creature):
def __init__(self, name):
super().__init__(name)
self.tooth = Tooth() # 组合
self.collar = None # 聚合:初始无项圈,可后续佩戴(如主人给戴的项圈)
4. 关联(Association):“长期的对象引用”(非整体-部分,对象间稳定联系)
定义:两个独立对象之间存在“有一个”(has-a)的长期引用关系,不涉及“整体-部分”,仅体现稳定的互动绑定。
场景:角色的“敌人列表”(enemies)存储多个生物(人、狗等),长期持有引用(即使不战斗,敌人关系也存在)。
class Human(Creature):
def __init__(self, name):
super().__init__(name)
self.fist = Fist()
self.weapon = None
self.enemies = [] # 关联:用列表存储多个敌人(长期引用,可是人/狗/其他生物)
def add_enemy(self, enemy):
"""添加敌人(管理关联关系):敌人必须是生物,且不能是自己"""
if isinstance(enemy, Creature) and enemy not in self.enemies and enemy != self:
self.enemies.append(enemy)
return f"{self.name}将{enemy.name}({type(enemy).__name__})列为敌人"
return f"无法将{getattr(enemy, 'name', '未知目标')}列为敌人"
def attack(self, target):
"""攻击指定目标(需验证目标是否在敌人列表中)"""
if not self.is_alive():
return f"{self.name}已倒下,无法攻击"
if target not in self.enemies:
return f"{target.name}不在{self.name}的敌人列表中,无法攻击"
if not target.is_alive():
return f"{target.name}已倒下,无需攻击"
# 用武器或拳头攻击(聚合/组合的应用)
damage = self.weapon.damage if self.weapon else self.fist.hit()
target.take_damage(damage)
weapon_name = self.weapon.name if self.weapon else "拳头"
return f"{self.name}用{weapon_name}攻击{target.name},造成{damage}点伤害"
class Dog(Creature):
def __init__(self, name):
super().__init__(name)
self.tooth = Tooth()
self.collar = None
self.enemies = [] # 关联:敌人列表(可包含人/狗等任何生物)
def add_enemy(self, enemy):
"""添加敌人(逻辑同人类)"""
if isinstance(enemy, Creature) and enemy not in self.enemies and enemy != self:
self.enemies.append(enemy)
return f"{self.name}将{enemy.name}({type(enemy).__name__})列为敌人"
return f"无法将{getattr(enemy, 'name', '未知目标')}列为敌人"
def bite(self, target):
"""撕咬指定目标(需验证目标是否在敌人列表中)"""
if not self.is_alive():
return f"{self.name}已倒下,无法撕咬"
if target not in self.enemies:
return f"{target.name}不在{self.name}的敌人列表中,无法撕咬"
if not target.is_alive():
return f"{target.name}已倒下,无需撕咬"
# 用牙齿撕咬,项圈减少敌人伤害(组合/聚合的应用)
damage = self.tooth.bite()
if self.collar:
damage -= self.collar.defense # 金属项圈减伤
damage = max(1, damage)
target.take_damage(damage)
return f"{self.name}撕咬{target.name},造成{damage}点伤害"
5. 依赖(Dependency):“临时的方法级使用”(用完即断,无长期引用)
定义:一个类的方法临时使用另一个类的对象,仅在方法调用时存在关系,不长期持有引用(用完即断)。
场景:战斗中临时使用“药水”疗伤,药水仅在使用时被引用,使用后角色不会保留对药水的引用。
class Potion:
"""治疗药水(被依赖的类:仅临时使用)"""
def __init__(self, heal_amount):
self.heal_amount = heal_amount # 治疗量
def restore(self, target):
"""临时为目标恢复生命值(仅在调用时生效)"""
target.hp = min(100, target.hp + self.heal_amount)
return f"药水为{target.name}恢复{self.heal_amount}血,当前{target.hp}血"
# 人类添加“使用药水”方法(依赖关系)
class Human(Creature):
# (省略之前的属性和方法)
def use_potion(self, potion):
"""临时使用药水(仅在调用时依赖potion对象)"""
return potion.restore(self) # 方法结束后,不持有potion的引用
大战场景演示(综合应用所有关系)
if __name__ == "__main__":
# 1. 创建角色(继承:都是生物)
alice = Human("Alice") # 人类主角
bob = Human("Bob") # 人类敌人
wangcai = Dog("旺财") # 狗敌人
laifu = Dog("来福") # 另一狗敌人
# 2. 建立关联:添加多种敌人(人/狗)
print("=== 关联:添加敌人列表 ===")
print(alice.add_enemy(bob)) # Alice的敌人:人类Bob
print(alice.add_enemy(wangcai))# Alice的敌人:狗旺财
print(alice.add_enemy(laifu)) # Alice的敌人:狗来福
print(bob.add_enemy(alice)) # Bob的敌人:Alice(人打人)
print(wangcai.add_enemy(alice))# 旺财的敌人:Alice(狗打人)
# 3. 装备聚合组件(武器/项圈)
alice.weapon = Weapon("长剑", 20) # Alice捡起长剑(聚合)
bob.weapon = Weapon("斧头", 18) # Bob拿起斧头(聚合)
wangcai.collar = Collar("金属") # 旺财戴上金属项圈(聚合)
# 4. 第一回合:人打人(关联+聚合+继承)
print("\n=== 第一回合:人打人 ===")
print(alice.attack(bob)) # Alice用长剑攻击Bob(聚合的武器)
print(bob.attack(alice)) # Bob用斧头反击(继承的受伤方法)
# 5. 第二回合:人打狗(关联+组合+聚合)
print("\n=== 第二回合:人打狗 ===")
print(alice.attack(wangcai))# Alice攻击旺财(验证在敌人列表中)
print(wangcai.bite(alice)) # 旺财撕咬(组合的牙齿+聚合的项圈减伤)
# 6. 第三回合:使用药水疗伤(依赖)
print("\n=== 第三回合:依赖(使用药水) ===")
small_potion = Potion(30) # 药水独立存在
print(alice.use_potion(small_potion)) # 临时使用,用完不持有
print("Alice是否持有药水?", hasattr(alice, "potion")) # 输出False(无长期引用)
运行结果
=== 关联:添加敌人列表 ===
Alice将Bob(Human)列为敌人
Alice将旺财(Dog)列为敌人
Alice将来福(Dog)列为敌人
Bob将Alice(Human)列为敌人
旺财将Alice(Human)列为敌人
=== 第一回合:人打人 ===
Alice用长剑攻击Bob,造成20点伤害
Bob受20点伤害,剩余80血
Bob用斧头攻击Alice,造成18点伤害
Alice受18点伤害,剩余82血
=== 第二回合:人打狗 ===
Alice用长剑攻击旺财,造成20点伤害
旺财受20点伤害,剩余80血
旺财撕咬Alice,造成6点伤害 # 牙齿伤害8 - 金属项圈防御2 = 6
Alice受6点伤害,剩余76血
=== 第三回合:依赖(使用药水) ===
药水为Alice恢复30血,当前100血
Alice是否持有药水? False
五种关系总结表
| 关系类型 | 核心定义(“是什么”) | 人狗大战场景体现 | 关键区别(与其他关系) |
|---|---|---|---|
| 继承 | 子类“是一种”父类(is-a),继承属性和方法 | 人和狗“是一种”生物,共享生命值和受伤逻辑 | 强调“类型归属”,通过super()复用代码 |
| 组合 | 整体“包含不可分离的部分”,部分依赖整体存在 | 人的拳头、狗的牙齿,不能脱离身体单独存在 | 部分是整体的“原生组件”,创建整体时自动生成 |
| 聚合 | 整体“包含可分离的部分”,部分可独立存在 | 人的武器、狗的项圈,可单独创建后附加 | 部分是整体的“附加组件”,可随时分离 |
| 关联 | 独立对象间的“长期引用关系”(非整体-部分) | 角色的敌人列表,长期存储人/狗等生物引用 | 强调“稳定互动绑定”,不涉及“包含”关系 |
| 依赖 | 方法级的“临时使用”,用完即断,无长期引用 | 临时使用药水疗伤,使用后不保留药水引用 | 强调“短期借用”,仅存在于方法调用时 |
通过这个场景可以清晰看到:继承负责“共性复用”,组合/聚合负责“整体与部分的不同绑定强度”,关联负责“对象间的长期互动”,依赖负责“临时资源的使用”。五种关系分工明确,共同构建了灵活且符合现实逻辑的面向对象模型。

浙公网安备 33010602011771号