人狗大战Ⅱ:融合了封装、继承、多态、鸭子类型、类属性 / 方法、静态方法、特殊方法、super、property、抽象基类、__slots__等语法特性

以下是一个稍微复杂的 “人狗大战” 面向对象实现,融合了封装、继承、多态、鸭子类型、类属性 / 方法、静态方法、特殊方法、super、property、slots 等语法特性,并在注释中详细说明:

from abc import ABC, abstractmethod  # 抽象基类,用于定义接口约束
import random

# 1. 抽象基类:定义所有战斗角色的接口(封装核心行为)
class Fighter(ABC):
    # 类属性:记录所有战斗角色的总数(类级别的状态)
    total_fighters = 0

    def __init__(self, name: str, hp: int, attack: int):
        self._name = name  # 单下划线:约定为内部属性,通过property暴露
        self._hp = hp      # 生命值,私有属性通过property控制访问
        self._attack = attack  # 基础攻击力
        Fighter.total_fighters += 1  # 每次实例化,总数+1

    # 用property装饰器封装属性访问,实现数据校验(封装的核心)
    @property
    def name(self) -> str:
        return self._name

    @property
    def hp(self) -> int:
        return self._hp

    @hp.setter
    def hp(self, value: int):
        # 确保生命值不会为负(封装的保护作用)
        self._hp = max(0, value)

    # 抽象方法:所有战斗角色必须实现攻击逻辑(多态的基础)
    @abstractmethod
    def attack(self, enemy: 'Fighter') -> None:
        pass

    # 特殊方法:自定义打印格式(增强可读性)
    def __str__(self) -> str:
        return f"{self.name}(生命值:{self.hp},攻击力:{self._attack})"

    # 特殊方法:定义对象的布尔值(用于判断是否存活)
    def __bool__(self) -> bool:
        return self.hp > 0

    # 类方法:获取当前战斗角色总数(操作类属性)
    @classmethod
    def get_total_count(cls) -> int:
        return cls.total_fighters

    # 静态方法:判断是否触发暴击(纯工具逻辑,无状态依赖)
    @staticmethod
    def is_critical() -> bool:
        return random.random() < 0.3  # 30%暴击概率


# 2. 人类角色:继承自Fighter,实现具体战斗逻辑
class Human(Fighter):
    # __slots__:限制实例可添加的属性,节省内存并防止误添加
    __slots__ = ('_name', '_hp', '_attack', '_weapon')#全是私有属性

    def __init__(self, name: str, hp: int = 100, attack: int = 25, weapon: str = "拳头"):
        # 调用父类构造方法(super的典型应用)
        super().__init__(name, hp, attack)
        self._weapon = weapon  # 武器类型

    # 重写攻击方法:实现人类特有的攻击逻辑(多态体现)
    def attack(self, enemy: Fighter) -> None:
        if not self:  # 利用__bool__判断自身是否存活
            print(f"{self.name}已倒下,无法攻击!")
            return

        # 基础伤害
        damage = self._attack
       
        # 武器加成:武器伤害翻倍(封装的保护作用)
        if self._weapon == "武器":
            damage *= 2

        # 暴击判定(调用父类静态方法)
        if Fighter.is_critical():
            damage *= 2
            crit_msg = "(暴击!)"
        else:
            crit_msg = ""

        # 应用伤害(通过property修改hp,触发数据校验)
        enemy.hp -= damage
        print(f"{self.name}用{self._weapon}攻击了{enemy.name},造成{damage}点伤害{crit_msg}!{enemy.name}剩余{enemy.hp}血")

    # 人类特有方法:使用药品回血
    def use_medicine(self, value: int) -> None:
        self.hp += value  # 通过property修改,确保不会溢出(虽然此处未限制上限)
        print(f"{self.name}使用药品回血{value}点,当前生命值:{self.hp}")


# 3. 狗类角色:继承自Fighter,实现不同攻击逻辑(多态)
class Dog(Fighter):
    __slots__ = ('_name', '_hp', '_attack', '_breed')  # 限制属性

    def __init__(self, name: str, breed: str, hp: int = 80, attack: int = 20):
        super().__init__(name, hp, attack)
        self._breed = breed  # 狗的品种

    # 重写攻击方法:狗的攻击逻辑(多态体现)
    def attack(self, enemy: Fighter) -> None:
        if not self:
            print(f"{self.name}已倒下,无法攻击!")
            return

        damage = self._attack
        # 品种加成:藏獒有额外伤害
        if self._breed == "藏獒":
            damage += 10

        enemy.hp -= damage
        print(f"{self.name}({self._breed})撕咬了{enemy.name},造成{damage}点伤害!{enemy.name}剩余{enemy.hp}血")

    # 狗特有方法:吠叫(威慑敌人)
    def bark(self) -> None:
        print(f"{self.name}发出凶狠的叫声:汪汪!{enemy.name}感到害怕!" if 'enemy' in locals() else f"{self.name}汪汪叫!")


# 4. 机器人角色:无继承Fighter,但实现了attack和hp属性(鸭子类型)
class Robot:
    """机器人:未继承Fighter,但有attack方法和hp属性,可参与战斗(鸭子类型)"""
    def __init__(self, name: str, hp: int = 150, attack: int = 30):
        self.name = name
        self.hp = hp  # 直接公开属性(对比Fighter的封装)
        self.attack_power = attack

    def attack(self, enemy: Fighter) -> None:
        if self.hp <= 0:
            print(f"{self.name}已瘫痪,无法攻击!")
            return

        damage = self.attack_power * 1.5  # 机器人攻击有稳定加成
        enemy.hp -= damage
        print(f"{self.name}发射激光攻击{enemy.name},造成{int(damage)}点伤害!{enemy.name}剩余{enemy.hp}血")

    # 实现__bool__,与Fighter保持一致的布尔判断逻辑
    def __bool__(self) -> bool:
        return self.hp > 0

    def __str__(self) -> str:
        return f"{self.name}(机器人,生命值:{self.hp},攻击力:{self.attack_power})"


# 5. 战斗管理器:负责组织战斗流程、执行战斗、管理战斗角色
class BattleManager:
    def __init__(self, fighters):# 初始化战斗管理器,接收Fighter和Robot列表 
        self.fighters = fighters  # 战斗角色列表(支持Fighter和Robot,体现鸭子类型)

    # 执行回合制战斗
    def start_battle(self, rounds: int = 3) -> None:
        print("=== 战斗开始 ===")
        for i in range(1, rounds + 1):
            print(f"\n----- 第{i}回合 -----")
            # 遍历所有角色,让存活的角色随机攻击另一个存活角色
            for attacker in self.fighters:
                if not attacker:  # 利用__bool__判断是否存活
                    continue
                # 筛选存活的敌人(排除自己)
                enemies = [f for f in self.fighters if f != attacker and f]
                if enemies:
                    target = random.choice(enemies)
                    attacker.attack(target)  # 多态调用:不同角色攻击逻辑不同
        print("\n=== 战斗结束 ===")
        # 打印存活角色
        survivors = [f for f in self.fighters if f]
        print(f"存活角色:{', '.join(str(f) for f in survivors)}")


# 6. 主程序:初始化角色并开始战斗
if __name__ == "__main__":
    # 创建战斗角色(人类、狗、机器人)
    human = Human("小明", hp=120, attack=30, weapon="火箭弹")
    dog1 = Dog("旺财", breed="藏獒", hp=100, attack=25)
    dog2 = Dog("小白", breed="京巴", hp=70, attack=15)
    robot = Robot("终结者T800", hp=200, attack=35)

    # 打印初始角色信息
    print("初始角色:")
    print(human, dog1, dog2, robot, sep="\n")
    print(f"当前Fighter总数:{Fighter.get_total_count()}(人类和狗属于Fighter子类,机器人属于Robot类)")

    # 人类使用药品(特有方法)
    human.use_medicine(30)
    # 狗吠叫(特有方法)
    dog1.bark()

    # 初始化战斗管理器并开始战斗
    battle = BattleManager([human, dog1, dog2, robot])
    battle.start_battle(rounds=4)  # 进行4回合战斗

代码中用到的面向对象语法总结:
封装:通过 property 控制属性访问(如 hp 的读写校验)、单下划线约定内部属性、slots 限制属性添加;
继承:Human 和 Dog 继承 Fighter 基类,复用属性和方法;
多态:Human、Dog、Robot 都实现 attack 方法,通过同一调用 attacker.attack(target) 触发不同逻辑;
鸭子类型:Robot 未继承 Fighter,但因有 attack 和 hp 可参与战斗;
类属性 / 方法:Fighter.total_fighters 统计总数,get_total_count 访问类属性;
静态方法:Fighter.is_critical 实现暴击判定(无状态依赖);
特殊方法:str 自定义打印、bool 定义存活判断;
抽象基类(ABC):Fighter 用 @abstractmethod 强制子类实现 attack;
super 函数:子类构造方法中调用父类 init
关联模式:BattleManager 关联多个 Fighter 管理战斗流程。
通过这些特性,代码既保证了逻辑的清晰性,又具备良好的扩展性(如新增 “猫” 角色只需实现 attack 方法即可加入战斗)。

posted @ 2025-10-22 11:50  wangya216  阅读(57)  评论(0)    收藏  举报